/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 */

#include "hellovk.h"
#include "fif.h"
#include <set>
#include <unordered_set>
#include <log.hpp>
#include <AAssetImporter.h>
#include <DescriptorPool.h>
#include <CommandPool.h>
#include <Utils.h>
#include <cstdio>
#include <cstring>
#include <thread>
#include <PerformanceProfiler.hpp>
#include <VulkanProfilingWrapper.hpp>

bool vkt::HelloVK::ENABLE_EXTRAPOLATION = false;
namespace vkt {
namespace {
// 静态标志，用于控制高频操作的日志输出
static bool s_loggedWaitForFences = false;
static bool s_loggedResetFences = false;
static bool s_loggedResetCommandPool = false;
static bool s_loggedAcquireNextImage = false;
static bool s_loggedBeginCommandBuffer = false;
static bool s_loggedEndCommandBuffer = false;
static bool s_loggedQueueSubmit = false;
static bool s_loggedQueuePresent = false;

[[nodiscard]] const char *ToStringMessageSeverity(VkDebugUtilsMessageSeverityFlagBitsEXT s)
{
    switch (s) {
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
            return "VERBOSE";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
            return "ERROR";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
            return "WARNING";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
            return "INFO";
        default:
            return "UNKNOWN";
    }
}

[[nodiscard]] const char *ToStringMessageType(VkDebugUtilsMessageTypeFlagsEXT s)
{
    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) {
        return "General | Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
        return "Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
        return "General";
    }

    return "Unknown";
}

VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
    VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
    void * /* pUserData */)
{
    static std::unordered_set<uint32_t> const validationFilter{ // Unspecified message. Safe to ignore it.
        0x00000000U, 0x675DC32EU
    };

    auto const messageID = static_cast<uint32_t>(pCallbackData->messageIdNumber);
    if (validationFilter.contains(messageID)) {
        return VK_FALSE;
    }

    auto ms = ToStringMessageSeverity(messageSeverity);
    auto mt = ToStringMessageType(messageType);
    GOLOGI("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage);

    return VK_FALSE;
}

void PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
{
    constexpr static VkValidationFeatureEnableEXT const validationFeatures[] = {
        VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
        VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT
    };

    constexpr static VkValidationFeaturesEXT validationInfo {
        .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
        .pNext = nullptr,
        .enabledValidationFeatureCount = static_cast<uint32_t>(std::size(validationFeatures)),
        .pEnabledValidationFeatures = validationFeatures,
        .disabledValidationFeatureCount = 0U,
        .pDisabledValidationFeatures = nullptr
    };

    createInfo = {};
    createInfo.pNext = &validationInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;

    createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;

    createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;

    createInfo.pfnUserCallback = &DebugCallback;
}


glm::mat4 ConvertGLMMat4ToMat4(glm::mat4 matrix)
{
    // 直接返回glm矩阵，不再需要转换
    return matrix;
}

/**
 * GetPrerotationMatrix handles screen rotation with 3 hardcoded rotation
 * matrices (detailed below). We skip the 180 degrees rotation.
 */
void GetPrerotationMatrix(const VkSurfaceCapabilitiesKHR &capabilities,
    const VkSurfaceTransformFlagBitsKHR &pretransformFlag, std::array<float, 16> &mat)
{
    // mat is initialized to the identity matrix
    mat = { 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
        // mat is set to a 90 deg rotation matrix
        mat = { 0., 1., 0., 0., -1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
        return;
    }

    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
        // mat is set to 270 deg rotation matrix
        mat = { 0., -1., 0., 0., 1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    }
}
} // end of anonymous namespace

void HelloVK::InitVulkan()
{
        // 启用性能分析器
        GOLOGI("=== Enabling Performance Profiler ===");
        PerformanceProfiler::Instance().Enable(true);
        
        CreateInstance();
        CreateSurface();
        PickPhysicalDevice();
        CreateLogicalDeviceAndQueue();
        SetupDebugMessenger();
        EstablishDisplaySizeIdentity();
        CreateSwapChain();
        CreateImageViews();
        FGInitDevice();
        FGCreateCommandPool();
        FGCreateColorResources();
        FGCreateDepthResources();
        OHTestApp::DescriptorPool::Instance().Init();
        FGCreateSwapchainSyncObjects();
        FGInitUIRenderer();
        // 将整个Vulkan初始化都移出主线程,试试能否完全避免ANR
        std::thread initThread([this]() {
            GOLOGI("=== Starting Vulkan initialization in background thread ===");
            FGInitMainSceneRenderer();

            GOLOGI("=== Vulkan core initialization completed ===");
            m_initialized = true;

            // 初始化完成后再API冒烟测试
            GOLOGI("=== Starting API smoke tests ===");
            RunApiSmokeTestsOnce();
            GOLOGI("=== All initialization completed ===");
        });
    
    initThread.detach();  // 分离线程，在后台独立运行
    
    GOLOGI("Vulkan initialization started in background thread, main thread continues");
}

// 辅助函数: 查找合适的内存类型
uint32_t HelloVK::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{
    VkPhysicalDeviceMemoryProperties memProperties;
    vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties);
    
    for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
        if ((typeFilter & (1 << i)) && 
            (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
            return i;
        }
    }
    GOLOGE("Failed to find suitable memory type");
    return 0;
}

// 辅助函数: 提交CommandBuffer并等待完成
void HelloVK::SubmitAndWait(VkCommandBuffer cmdBuffer)
{
    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &cmdBuffer;
    
    VkResult result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
    if (result == VK_SUCCESS) {
        result = vkQueueWaitIdle(m_graphicsQueue);
        if (result != VK_SUCCESS) {
            GOLOGE("vkQueueWaitIdle failed with error: %d", result);
        }
    } else {
        GOLOGE("vkQueueSubmit failed with error: %d", result);
    }
}

// 辅助函数: 验证设备地址
bool HelloVK::ValidateDeviceAddress(VkDeviceAddress address, const char* apiName)
{
    if (address == 0) {
        GOLOGE("%s returned null address", apiName);
        return false;
    }
    if (address % 4 != 0) {
        GOLOGW("%s returned unaligned address: 0x%llx", apiName, 
               static_cast<unsigned long long>(address));
    }
    return true;
}

void HelloVK::RunApiSmokeTestsOnce()
{
    static bool s_tested = false;
    if (s_tested) return;
    s_tested = true;

    static bool s_loggedGetDeviceMemoryOpaqueCaptureAddress = false;
    static bool s_loggedGetDeviceProcAddr = false;

    GOLOGI("=== Starting Vulkan API Smoke Tests ===");
    // 测试 vkGetPipelineCacheData
    {
        static bool s_loggedGetPipelineCacheData = false;
        if (!s_loggedGetPipelineCacheData) {
            VkPipelineCacheCreateInfo cacheInfo{};
            cacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
            cacheInfo.initialDataSize = 0;
            cacheInfo.pInitialData = nullptr;
            
            VkPipelineCache testCache = VK_NULL_HANDLE;
            VkResult result = vkCreatePipelineCache(m_device, &cacheInfo, nullptr, &testCache);
            
            if (result == VK_SUCCESS && testCache != VK_NULL_HANDLE) {
                size_t dataSize = 0;
                VkResult getResult = vkGetPipelineCacheData(m_device, testCache, &dataSize, nullptr);
                
                if (getResult == VK_SUCCESS) {
                    GOLOGW("vkGetPipelineCacheData completed successfully (cache size: %zu bytes)", dataSize);
                    
                    if (dataSize > 0) {
                        std::vector<uint8_t> cacheData(dataSize);
                        getResult = vkGetPipelineCacheData(m_device, testCache, &dataSize, cacheData.data());
                        
                        if (getResult == VK_SUCCESS) {
                            GOLOGI("vkGetPipelineCacheData retrieved cache data successfully");
                        } else {
                            GOLOGE("vkGetPipelineCacheData failed to retrieve cache data with error: %d", getResult);
                        }
                    }
                } else {
                    GOLOGE("vkGetPipelineCacheData failed with error: %d", getResult);
                }
                
                vkDestroyPipelineCache(m_device, testCache, nullptr);
            } else {
                GOLOGE("vkGetPipelineCacheData test skipped: pipeline cache creation failed with error %d", result);
            }
            s_loggedGetPipelineCacheData = true;
        }
    }

    // 测试 vkGetPrivateData
    {
        static bool s_loggedGetPrivateData = false;
        if (!s_loggedGetPrivateData) {
            auto pGetPrivateData = reinterpret_cast<PFN_vkGetPrivateData>(
                vkGetDeviceProcAddr(m_device, "vkGetPrivateData"));
            
            if (pGetPrivateData) {
                VkPrivateDataSlotCreateInfo slotInfo{};
                slotInfo.sType = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO;
                slotInfo.flags = 0;
                
                VkPrivateDataSlot dataSlot = VK_NULL_HANDLE;
                
                auto pCreatePrivateDataSlot = reinterpret_cast<PFN_vkCreatePrivateDataSlot>(
                    vkGetDeviceProcAddr(m_device, "vkCreatePrivateDataSlot"));
                
                if (pCreatePrivateDataSlot) {
                    VkResult result = pCreatePrivateDataSlot(m_device, &slotInfo, nullptr, &dataSlot);
                    
                    if (result == VK_SUCCESS && dataSlot != VK_NULL_HANDLE) {
                        uint64_t privateData = 0;
                        pGetPrivateData(m_device, VK_OBJECT_TYPE_DEVICE, reinterpret_cast<uint64_t>(m_device), 
                                       dataSlot, &privateData);
                        
                        GOLOGW("vkGetPrivateData completed successfully (retrieved data: 0x%llx)", 
                               static_cast<unsigned long long>(privateData));
                        
                        auto pDestroyPrivateDataSlot = reinterpret_cast<PFN_vkDestroyPrivateDataSlot>(
                            vkGetDeviceProcAddr(m_device, "vkDestroyPrivateDataSlot"));
                        if (pDestroyPrivateDataSlot) {
                            pDestroyPrivateDataSlot(m_device, dataSlot, nullptr);
                        }
                    } else {
                        GOLOGE("vkGetPrivateData test skipped: private data slot creation failed with error %d", result);
                    }
                } else {
                    GOLOGE("vkGetPrivateData test skipped: vkCreatePrivateDataSlot function NOT available");
                }
            } else {
                GOLOGE("vkGetPrivateData function NOT available (requires Vulkan 1.3 support)");
            }
            s_loggedGetPrivateData = true;
        }
    }

    // 测试 vkGetQueryPoolResults
    {
        static bool s_loggedGetQueryPoolResults = false;
        if (!s_loggedGetQueryPoolResults) {
            // 检查queue family是否支持timestamp query
            uint32_t queueFamilyCount = 0;
            vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr);
            std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
            vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data());
            
            bool timestampSupported = false;
            for (const auto& queueFamily : queueFamilies) {
                if (queueFamily.timestampValidBits > 0) {
                    timestampSupported = true;
                    break;
                }
            }
            
            if (!timestampSupported) {
                GOLOGI("vkGetQueryPoolResults test skipped: device does not support timestamp queries");
                s_loggedGetQueryPoolResults = true;
            } else {
                auto pResetQueryPool = reinterpret_cast<PFN_vkResetQueryPool>(
                    vkGetDeviceProcAddr(m_device, "vkResetQueryPool"));
                
                VkQueryPoolCreateInfo queryPoolInfo{};
                queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
                queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
                queryPoolInfo.queryCount = 2;
                
                VkQueryPool testQueryPool = VK_NULL_HANDLE;
                VkResult result = vkCreateQueryPool(m_device, &queryPoolInfo, nullptr, &testQueryPool);
            
            if (result == VK_SUCCESS && testQueryPool != VK_NULL_HANDLE) {
                // 创建临时CommandBuffer来写入timestamp query
                VkCommandPoolCreateInfo cmdPoolInfo{};
                cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                cmdPoolInfo.queueFamilyIndex = 0;  // 假设graphics queue family index为0
                cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                
                VkCommandPool tempCmdPool = VK_NULL_HANDLE;
                result = vkCreateCommandPool(m_device, &cmdPoolInfo, nullptr, &tempCmdPool);
                
                if (result == VK_SUCCESS && tempCmdPool != VK_NULL_HANDLE) {
                    VkCommandBufferAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                    allocInfo.commandPool = tempCmdPool;
                    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                    allocInfo.commandBufferCount = 1;
                    
                    VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                    result = vkAllocateCommandBuffers(m_device, &allocInfo, &tempCmdBuffer);
                    
                    if (result == VK_SUCCESS && tempCmdBuffer != VK_NULL_HANDLE) {
                        // 开始录制CommandBuffer
                        VkCommandBufferBeginInfo beginInfo{};
                        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                        beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
                        
                        result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                        
                        if (result == VK_SUCCESS) {
                            // 重置query pool
                            if (pResetQueryPool) {
                                vkCmdResetQueryPool(tempCmdBuffer, testQueryPool, 0, 2);
                            }
                            
                            // 写入两个timestamp查询
                            vkCmdWriteTimestamp(tempCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, testQueryPool, 0);
                            vkCmdWriteTimestamp(tempCmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, testQueryPool, 1);
                            
                            vkEndCommandBuffer(tempCmdBuffer);
                            
                            // 提交并等待完成
                            VkSubmitInfo submitInfo{};
                            submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
                            submitInfo.commandBufferCount = 1;
                            submitInfo.pCommandBuffers = &tempCmdBuffer;
                            
                            result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
                            
                            if (result == VK_SUCCESS) {
                                // 等待队列执行完成
                                result = vkQueueWaitIdle(m_graphicsQueue);
                                
                                if (result == VK_SUCCESS) {
                                    // 现在读取query结果
                                    uint64_t queryResults[4] = {0, 0, 0, 0};  // 每个query 2个uint64(结果+可用性标志)
                                    VkResult queryResult = vkGetQueryPoolResults(
                                        m_device, testQueryPool, 0, 2, 
                                        sizeof(queryResults), queryResults, 
                                        sizeof(uint64_t) * 2, 
                                        VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | VK_QUERY_RESULT_WAIT_BIT);
                                    
                                    if (queryResult == VK_SUCCESS) {
                                        // 检查可用性标志
                                        bool query0Available = (queryResults[1] != 0);
                                        bool query1Available = (queryResults[3] != 0);
                                        
                                        if (query0Available && query1Available) {
                                            uint64_t timestamp0 = queryResults[0];
                                            uint64_t timestamp1 = queryResults[2];
                                            
                                            // 计算时间差 (以纳秒为单位)
                                            float timestampPeriod = m_physicalDeviceProperties.limits.timestampPeriod;
                                            uint64_t timeDiffNs = static_cast<uint64_t>((timestamp1 - timestamp0) * timestampPeriod);
                                            
                                            GOLOGW("vkGetQueryPoolResults completed successfully (timestamp0: %llu, timestamp1: %llu, time diff: %llu ns)", 
                                                   static_cast<unsigned long long>(timestamp0),
                                                   static_cast<unsigned long long>(timestamp1),
                                                   static_cast<unsigned long long>(timeDiffNs));
                                        } else {
                                            GOLOGI("vkGetQueryPoolResults: query results available but some queries not ready (query0: %d, query1: %d)", 
                                                   query0Available ? 1 : 0, query1Available ? 1 : 0);
                                        }
                                    } else if (queryResult == VK_NOT_READY) {
                                        GOLOGI("vkGetQueryPoolResults returned VK_NOT_READY (unexpected after vkQueueWaitIdle)");
                                    } else {
                                        GOLOGE("vkGetQueryPoolResults failed with error: %d", queryResult);
                                    }
                                } else {
                                    GOLOGE("vkQueueWaitIdle failed with error: %d", result);
                                }
                            } else {
                                GOLOGE("vkQueueSubmit failed with error: %d", result);
                            }
                        } else {
                            GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                        }
                        
                        // 清理CommandBuffer (不需要手动释放,销毁pool会自动释放)
                    } else {
                        GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                    }
                    
                    // 清理CommandPool
                    vkDestroyCommandPool(m_device, tempCmdPool, nullptr);
                } else {
                    GOLOGE("vkCreateCommandPool failed with error: %d", result);
                }
                
                // 清理QueryPool
                vkDestroyQueryPool(m_device, testQueryPool, nullptr);
            } else {
                GOLOGE("vkGetQueryPoolResults test skipped: query pool creation failed with error %d", result);
            }
                s_loggedGetQueryPoolResults = true;
            }
        }
    }

    // 测试 vkGetRenderAreaGranularity
    {
        static bool s_loggedGetRenderAreaGranularity = false;
        if (!s_loggedGetRenderAreaGranularity) {
            VkAttachmentDescription colorAttachment{};
            colorAttachment.format = m_swapChainImageFormat;
            colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
            colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
            colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
            colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
            colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
            colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
            
            VkAttachmentReference colorAttachmentRef{};
            colorAttachmentRef.attachment = 0;
            colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
            
            VkSubpassDescription subpass{};
            subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
            subpass.colorAttachmentCount = 1;
            subpass.pColorAttachments = &colorAttachmentRef;
            
            VkRenderPassCreateInfo renderPassInfo{};
            renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
            renderPassInfo.attachmentCount = 1;
            renderPassInfo.pAttachments = &colorAttachment;
            renderPassInfo.subpassCount = 1;
            renderPassInfo.pSubpasses = &subpass;
            
            VkRenderPass testRenderPass = VK_NULL_HANDLE;
            VkResult result = vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &testRenderPass);
            
            if (result == VK_SUCCESS && testRenderPass != VK_NULL_HANDLE) {
                VkExtent2D granularity{};
                vkGetRenderAreaGranularity(m_device, testRenderPass, &granularity);
                
                GOLOGW("vkGetRenderAreaGranularity completed successfully (granularity: %ux%u)", 
                       granularity.width, granularity.height);
                
                vkDestroyRenderPass(m_device, testRenderPass, nullptr);
            } else {
                GOLOGE("vkGetRenderAreaGranularity test skipped: render pass creation failed with error %d", result);
            }
            s_loggedGetRenderAreaGranularity = true;
        }
    }

    // 测试 vkGetSemaphoreCounterValue
    {
        static bool s_loggedGetSemaphoreCounterValue = false;
        if (!s_loggedGetSemaphoreCounterValue) {
            auto pGetSemaphoreCounterValue = reinterpret_cast<PFN_vkGetSemaphoreCounterValue>(
                vkGetDeviceProcAddr(m_device, "vkGetSemaphoreCounterValue"));
            
            if (pGetSemaphoreCounterValue) {
                VkSemaphoreTypeCreateInfo timelineInfo{};
                timelineInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
                timelineInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
                timelineInfo.initialValue = 0;
                
                VkSemaphoreCreateInfo semaphoreInfo{};
                semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
                semaphoreInfo.pNext = &timelineInfo;
                
                VkSemaphore timelineSemaphore = VK_NULL_HANDLE;
                VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &timelineSemaphore);
                
                if (result == VK_SUCCESS && timelineSemaphore != VK_NULL_HANDLE) {
                    uint64_t counterValue = 0;
                    VkResult getResult = pGetSemaphoreCounterValue(m_device, timelineSemaphore, &counterValue);
                    
                    if (getResult == VK_SUCCESS) {
                        GOLOGW("vkGetSemaphoreCounterValue completed successfully (counter value: %llu)", 
                               static_cast<unsigned long long>(counterValue));
                    } else {
                        GOLOGE("vkGetSemaphoreCounterValue failed with error: %d", getResult);
                    }
                    
                    vkDestroySemaphore(m_device, timelineSemaphore, nullptr);
                } else {
                    GOLOGE("vkGetSemaphoreCounterValue test skipped: timeline semaphore creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkGetSemaphoreCounterValue function NOT available (requires Vulkan 1.2+ support)");
            }
            s_loggedGetSemaphoreCounterValue = true;
        }
    }

    // 测试 vkInvalidateMappedMemoryRanges
    {
        static bool s_loggedInvalidateMappedMemoryRanges = false;
        if (!s_loggedInvalidateMappedMemoryRanges) {
            VkBufferCreateInfo bufferInfo{};
            bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bufferInfo.size = 1024;
            bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
            bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
            
            VkBuffer testBuffer = VK_NULL_HANDLE;
            VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &testBuffer);
            
            if (result == VK_SUCCESS && testBuffer != VK_NULL_HANDLE) {
                VkMemoryRequirements memReqs;
                vkGetBufferMemoryRequirements(m_device, testBuffer, &memReqs);
                
                VkMemoryAllocateInfo allocInfo{};
                allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                allocInfo.allocationSize = memReqs.size;
                allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
                
                VkDeviceMemory testMemory = VK_NULL_HANDLE;
                result = vkAllocateMemory(m_device, &allocInfo, nullptr, &testMemory);
                
                if (result == VK_SUCCESS && testMemory != VK_NULL_HANDLE) {
                    result = vkBindBufferMemory(m_device, testBuffer, testMemory, 0);
                    
                    if (result == VK_SUCCESS) {
                        void* mappedData = nullptr;
                        result = vkMapMemory(m_device, testMemory, 0, memReqs.size, 0, &mappedData);
                        
                        if (result == VK_SUCCESS && mappedData != nullptr) {
                            VkMappedMemoryRange invalidateRange{};
                            invalidateRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
                            invalidateRange.memory = testMemory;
                            invalidateRange.offset = 0;
                            invalidateRange.size = memReqs.size;
                            
                            VkResult invalidateResult = vkInvalidateMappedMemoryRanges(m_device, 1, &invalidateRange);
                            
                            if (invalidateResult == VK_SUCCESS) {
                                GOLOGW("vkInvalidateMappedMemoryRanges completed successfully");
                            } else {
                                GOLOGE("vkInvalidateMappedMemoryRanges failed with error: %d", invalidateResult);
                            }
                            
                            vkUnmapMemory(m_device, testMemory);
                        } else {
                            GOLOGE("vkMapMemory failed with error: %d", result);
                        }
                    } else {
                        GOLOGE("vkBindBufferMemory failed with error: %d", result);
                    }
                    
                    vkFreeMemory(m_device, testMemory, nullptr);
                } else {
                    GOLOGE("vkInvalidateMappedMemoryRanges test skipped: memory allocation failed with error %d", result);
                }
                
                vkDestroyBuffer(m_device, testBuffer, nullptr);
            } else {
                GOLOGE("vkInvalidateMappedMemoryRanges test skipped: buffer creation failed with error %d", result);
            }
            s_loggedInvalidateMappedMemoryRanges = true;
        }
    }

    // 测试 vkMergePipelineCaches
    {
        static bool s_loggedMergePipelineCaches = false;
        if (!s_loggedMergePipelineCaches) {
            VkPipelineCacheCreateInfo cacheInfo{};
            cacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
            
            VkPipelineCache srcCache = VK_NULL_HANDLE;
            VkPipelineCache dstCache = VK_NULL_HANDLE;
            
            VkResult result = vkCreatePipelineCache(m_device, &cacheInfo, nullptr, &srcCache);
            if (result == VK_SUCCESS && srcCache != VK_NULL_HANDLE) {
                result = vkCreatePipelineCache(m_device, &cacheInfo, nullptr, &dstCache);
                
                if (result == VK_SUCCESS && dstCache != VK_NULL_HANDLE) {
                    VkResult mergeResult = vkMergePipelineCaches(m_device, dstCache, 1, &srcCache);
                    
                    if (mergeResult == VK_SUCCESS) {
                        GOLOGW("vkMergePipelineCaches completed successfully");
                    } else {
                        GOLOGE("vkMergePipelineCaches failed with error: %d", mergeResult);
                    }
                    
                    vkDestroyPipelineCache(m_device, dstCache, nullptr);
                } else {
                    GOLOGE("vkMergePipelineCaches test skipped: destination cache creation failed with error %d", result);
                }
                
                vkDestroyPipelineCache(m_device, srcCache, nullptr);
            } else {
                GOLOGE("vkMergePipelineCaches test skipped: source cache creation failed with error %d", result);
            }
            s_loggedMergePipelineCaches = true;
        }
    }

    // 测试 vkQueueBindSparse
    {
        static bool s_loggedQueueBindSparse = false;
        if (!s_loggedQueueBindSparse) {
            VkPhysicalDeviceFeatures features;
            vkGetPhysicalDeviceFeatures(m_physicalDevice, &features);
            
            if (!features.sparseBinding) {
                // 不支持sparse binding特性，则输出日志并执行最小化测试
                GOLOGE("vkQueueBindSparse test: device does NOT support sparse binding feature");
                GOLOGE("  Device: %s", m_physicalDeviceProperties.deviceName);
                GOLOGE("  API Version: %u.%u.%u", 
                       VK_VERSION_MAJOR(m_physicalDeviceProperties.apiVersion),
                       VK_VERSION_MINOR(m_physicalDeviceProperties.apiVersion),
                       VK_VERSION_PATCH(m_physicalDeviceProperties.apiVersion));
                GOLOGE("  Driver Version: %u", m_physicalDeviceProperties.driverVersion);
                GOLOGE("  Vendor ID: 0x%x", m_physicalDeviceProperties.vendorID);
                GOLOGE("  Device ID: 0x%x", m_physicalDeviceProperties.deviceID);
                
                // 输出相关的sparse特性支持情况
                GOLOGE("  Sparse Features Support:");
                GOLOGE("    sparseBinding: %s", features.sparseBinding ? "YES" : "NO");
                GOLOGE("    sparseResidencyBuffer: %s", features.sparseResidencyBuffer ? "YES" : "NO");
                GOLOGE("    sparseResidencyImage2D: %s", features.sparseResidencyImage2D ? "YES" : "NO");
                GOLOGE("    sparseResidencyImage3D: %s", features.sparseResidencyImage3D ? "YES" : "NO");
                GOLOGE("    sparseResidency2Samples: %s", features.sparseResidency2Samples ? "YES" : "NO");
                GOLOGE("    sparseResidency4Samples: %s", features.sparseResidency4Samples ? "YES" : "NO");
                GOLOGE("    sparseResidency8Samples: %s", features.sparseResidency8Samples ? "YES" : "NO");
                GOLOGE("    sparseResidency16Samples: %s", features.sparseResidency16Samples ? "YES" : "NO");
                GOLOGE("    sparseResidencyAliased: %s", features.sparseResidencyAliased ? "YES" : "NO");
                
                // 执行最小化测试方案：仅测试API调用但使用空参数
                GOLOGI("vkQueueBindSparse: attempting minimal test (empty bind operation)...");
                
                VkBindSparseInfo minimalBindInfo{};
                minimalBindInfo.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
                minimalBindInfo.waitSemaphoreCount = 0;
                minimalBindInfo.pWaitSemaphores = nullptr;
                minimalBindInfo.bufferBindCount = 0;
                minimalBindInfo.pBufferBinds = nullptr;
                minimalBindInfo.imageOpaqueBindCount = 0;
                minimalBindInfo.pImageOpaqueBinds = nullptr;
                minimalBindInfo.imageBindCount = 0;
                minimalBindInfo.pImageBinds = nullptr;
                minimalBindInfo.signalSemaphoreCount = 0;
                minimalBindInfo.pSignalSemaphores = nullptr;
                
                VkResult minimalResult = vkQueueBindSparse(m_graphicsQueue, 1, &minimalBindInfo, VK_NULL_HANDLE);
                
                if (minimalResult == VK_SUCCESS) {
                    GOLOGW("vkQueueBindSparse completed successfully [MINIMAL TEST: empty bind operation, no actual sparse resources]");
                } else if (minimalResult == VK_ERROR_FEATURE_NOT_PRESENT) {
                    GOLOGE("vkQueueBindSparse returned VK_ERROR_FEATURE_NOT_PRESENT [MINIMAL TEST: feature not supported by driver]");
                } else {
                    GOLOGE("vkQueueBindSparse failed with error: %d [MINIMAL TEST: empty bind operation]", minimalResult);
                }
                
                s_loggedQueueBindSparse = true;
            } else {
                GOLOGI("vkQueueBindSparse test: device supports sparse binding, running full test...");
                
                // 创建sparse buffer
                VkBufferCreateInfo bufferInfo{};
                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                bufferInfo.size = 65536; // 64KB
                bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
                bufferInfo.flags = VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                
                VkBuffer sparseBuffer = VK_NULL_HANDLE;
                VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &sparseBuffer);
                
                if (result == VK_SUCCESS && sparseBuffer != VK_NULL_HANDLE) {
                    // 获取sparse内存需求
                    VkMemoryRequirements memReqs;
                    vkGetBufferMemoryRequirements(m_device, sparseBuffer, &memReqs);
                    
                    // 获取sparse内存绑定要求
                    uint32_t sparseReqCount = 0;
                    vkGetImageSparseMemoryRequirements(m_device, VK_NULL_HANDLE, &sparseReqCount, nullptr);
                    
                    // 分配设备内存 (分配整块内存用于测试)
                    VkMemoryAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                    allocInfo.allocationSize = memReqs.size;
                    allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                    
                    VkDeviceMemory sparseMemory = VK_NULL_HANDLE;
                    result = vkAllocateMemory(m_device, &allocInfo, nullptr, &sparseMemory);
                    
                    if (result == VK_SUCCESS && sparseMemory != VK_NULL_HANDLE) {
                        // 创建sparse内存绑定
                        VkSparseMemoryBind memoryBind{};
                        memoryBind.resourceOffset = 0;
                        memoryBind.size = memReqs.size;
                        memoryBind.memory = sparseMemory;
                        memoryBind.memoryOffset = 0;
                        memoryBind.flags = 0;
                        
                        VkSparseBufferMemoryBindInfo bufferBindInfo{};
                        bufferBindInfo.buffer = sparseBuffer;
                        bufferBindInfo.bindCount = 1;
                        bufferBindInfo.pBinds = &memoryBind;
                        
                        // 创建fence用于同步
                        VkFenceCreateInfo fenceInfo{};
                        fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
                        
                        VkFence sparseFence = VK_NULL_HANDLE;
                        result = vkCreateFence(m_device, &fenceInfo, nullptr, &sparseFence);
                        
                        if (result == VK_SUCCESS && sparseFence != VK_NULL_HANDLE) {
                            // 提交sparse绑定操作
                            VkBindSparseInfo bindInfo{};
                            bindInfo.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
                            bindInfo.waitSemaphoreCount = 0;
                            bindInfo.pWaitSemaphores = nullptr;
                            bindInfo.bufferBindCount = 1;
                            bindInfo.pBufferBinds = &bufferBindInfo;
                            bindInfo.imageOpaqueBindCount = 0;
                            bindInfo.pImageOpaqueBinds = nullptr;
                            bindInfo.imageBindCount = 0;
                            bindInfo.pImageBinds = nullptr;
                            bindInfo.signalSemaphoreCount = 0;
                            bindInfo.pSignalSemaphores = nullptr;
                            
                            VkResult bindResult = vkQueueBindSparse(m_graphicsQueue, 1, &bindInfo, sparseFence);
                            
                            if (bindResult == VK_SUCCESS) {
                                // 等待绑定操作完成
                                VkResult waitResult = vkWaitForFences(m_device, 1, &sparseFence, VK_TRUE, UINT64_MAX);
                                
                                if (waitResult == VK_SUCCESS) {
                                    GOLOGW("vkQueueBindSparse completed successfully (bound %llu bytes to sparse buffer)",
                                           static_cast<unsigned long long>(memReqs.size));
                                } else {
                                    GOLOGE("vkQueueBindSparse: fence wait failed with error: %d", waitResult);
                                }
                            } else {
                                GOLOGE("vkQueueBindSparse failed with error: %d", bindResult);
                            }
                            
                            vkDestroyFence(m_device, sparseFence, nullptr);
                        } else {
                            GOLOGE("vkQueueBindSparse test: fence creation failed with error %d", result);
                        }
                        
                        vkFreeMemory(m_device, sparseMemory, nullptr);
                    } else {
                        GOLOGE("vkQueueBindSparse test: memory allocation failed with error %d", result);
                    }
                    
                    vkDestroyBuffer(m_device, sparseBuffer, nullptr);
                } else {
                    GOLOGE("vkQueueBindSparse test: sparse buffer creation failed with error %d", result);
                }
                s_loggedQueueBindSparse = true;
            }
        }
    }

    // 测试 vkResetCommandBuffer
    {
        static bool s_loggedResetCommandBuffer = false;
        if (!s_loggedResetCommandBuffer) {
            VkCommandPoolCreateInfo poolInfo{};
            poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
            poolInfo.queueFamilyIndex = 0;
            poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
            
            VkCommandPool testPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &testPool);
            
            if (result == VK_SUCCESS && testPool != VK_NULL_HANDLE) {
                VkCommandBufferAllocateInfo allocInfo{};
                allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                allocInfo.commandPool = testPool;
                allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                allocInfo.commandBufferCount = 1;
                
                VkCommandBuffer testCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(m_device, &allocInfo, &testCmdBuffer);
                
                if (result == VK_SUCCESS && testCmdBuffer != VK_NULL_HANDLE) {
                    VkCommandBufferBeginInfo beginInfo{};
                    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                    
                    result = vkBeginCommandBuffer(testCmdBuffer, &beginInfo);
                    if (result == VK_SUCCESS) {
                        result = vkEndCommandBuffer(testCmdBuffer);
                        
                        if (result == VK_SUCCESS) {
                            VkResult resetResult = vkResetCommandBuffer(testCmdBuffer, 0);
                            
                            if (resetResult == VK_SUCCESS) {
                                GOLOGW("vkResetCommandBuffer completed successfully");
                            } else {
                                GOLOGE("vkResetCommandBuffer failed with error: %d", resetResult);
                            }
                        } else {
                            GOLOGE("vkEndCommandBuffer failed with error: %d", result);
                        }
                    } else {
                        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                    }
                } else {
                    GOLOGE("vkResetCommandBuffer test skipped: command buffer allocation failed with error %d", result);
                }
                
                vkDestroyCommandPool(m_device, testPool, nullptr);
            } else {
                GOLOGE("vkResetCommandBuffer test skipped: command pool creation failed with error %d", result);
            }
            s_loggedResetCommandBuffer = true;
        }
    }

    // 测试 vkResetDescriptorPool
    {
        static bool s_loggedResetDescriptorPool = false;
        if (!s_loggedResetDescriptorPool) {
            VkDescriptorPoolSize poolSize{};
            poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
            poolSize.descriptorCount = 10;
            
            VkDescriptorPoolCreateInfo poolInfo{};
            poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
            poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
            poolInfo.maxSets = 10;
            poolInfo.poolSizeCount = 1;
            poolInfo.pPoolSizes = &poolSize;
            
            VkDescriptorPool testPool = VK_NULL_HANDLE;
            VkResult result = vkCreateDescriptorPool(m_device, &poolInfo, nullptr, &testPool);
            
            if (result == VK_SUCCESS && testPool != VK_NULL_HANDLE) {
                VkResult resetResult = vkResetDescriptorPool(m_device, testPool, 0);
                
                if (resetResult == VK_SUCCESS) {
                    GOLOGW("vkResetDescriptorPool completed successfully");
                } else {
                    GOLOGE("vkResetDescriptorPool failed with error: %d", resetResult);
                }
                
                vkDestroyDescriptorPool(m_device, testPool, nullptr);
            } else {
                GOLOGE("vkResetDescriptorPool test skipped: descriptor pool creation failed with error %d", result);
            }
            s_loggedResetDescriptorPool = true;
        }
    }

    // 测试 vkResetQueryPool
    {
        static bool s_loggedResetQueryPool = false;
        if (!s_loggedResetQueryPool) {
            auto pResetQueryPool = reinterpret_cast<PFN_vkResetQueryPool>(
                vkGetDeviceProcAddr(m_device, "vkResetQueryPool"));
            
            if (pResetQueryPool) {
                uint32_t queueFamilyCount = 0;
                vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr);
                std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
                vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data());
                
                bool timestampSupported = false;
                for (const auto& queueFamily : queueFamilies) {
                    if (queueFamily.timestampValidBits > 0) {
                        timestampSupported = true;
                        break;
                    }
                }
                
                if (timestampSupported) {
                    VkQueryPoolCreateInfo queryPoolInfo{};
                    queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
                    queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
                    queryPoolInfo.queryCount = 2;
                    
                    VkQueryPool testQueryPool = VK_NULL_HANDLE;
                    VkResult result = vkCreateQueryPool(m_device, &queryPoolInfo, nullptr, &testQueryPool);
                    
                    if (result == VK_SUCCESS && testQueryPool != VK_NULL_HANDLE) {
                        // 创建临时CommandBuffer来使用query pool
                        VkCommandPoolCreateInfo cmdPoolInfo{};
                        cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                        cmdPoolInfo.queueFamilyIndex = 0;
                        cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                        
                        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
                        result = vkCreateCommandPool(m_device, &cmdPoolInfo, nullptr, &tempCmdPool);
                        
                        if (result == VK_SUCCESS && tempCmdPool != VK_NULL_HANDLE) {
                            VkCommandBufferAllocateInfo allocInfo{};
                            allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                            allocInfo.commandPool = tempCmdPool;
                            allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                            allocInfo.commandBufferCount = 1;
                            
                            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                            result = vkAllocateCommandBuffers(m_device, &allocInfo, &tempCmdBuffer);
                            
                            if (result == VK_SUCCESS && tempCmdBuffer != VK_NULL_HANDLE) {
                                // 开始录制CommandBuffer
                                VkCommandBufferBeginInfo beginInfo{};
                                beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
                                
                                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                                
                                if (result == VK_SUCCESS) {
                                    // 在command buffer中先重置query pool
                                    vkCmdResetQueryPool(tempCmdBuffer, testQueryPool, 0, 2);
                                    
                                    // 写入timestamp使query pool被使用
                                    vkCmdWriteTimestamp(tempCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, testQueryPool, 0);
                                    vkCmdWriteTimestamp(tempCmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, testQueryPool, 1);
                                    
                                    vkEndCommandBuffer(tempCmdBuffer);
                                    
                                    // 提交并等待完成
                                    VkSubmitInfo submitInfo{};
                                    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
                                    submitInfo.commandBufferCount = 1;
                                    submitInfo.pCommandBuffers = &tempCmdBuffer;
                                    
                                    result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
                                    
                                    if (result == VK_SUCCESS) {
                                        result = vkQueueWaitIdle(m_graphicsQueue);
                                        
                                        if (result == VK_SUCCESS) {
                                            // 现在query pool已被使用,测试host端的vkResetQueryPool
                                            pResetQueryPool(m_device, testQueryPool, 0, 2);
                                            GOLOGW("vkResetQueryPool completed successfully (reset query pool after usage)");
                                        } else {
                                            GOLOGE("vkQueueWaitIdle failed with error: %d", result);
                                        }
                                    } else {
                                        GOLOGE("vkQueueSubmit failed with error: %d", result);
                                    }
                                } else {
                                    GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                }
                            } else {
                                GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                            }
                            
                            vkDestroyCommandPool(m_device, tempCmdPool, nullptr);
                        } else {
                            GOLOGE("vkCreateCommandPool failed with error: %d", result);
                        }
                        
                        vkDestroyQueryPool(m_device, testQueryPool, nullptr);
                    } else {
                        GOLOGE("vkResetQueryPool test skipped: query pool creation failed with error %d", result);
                    }
                } else {
                    GOLOGI("vkResetQueryPool test skipped: device does not support timestamp queries");
                }
            } else {
                GOLOGE("vkResetQueryPool function NOT available (requires Vulkan 1.2+ support)");
            }
            s_loggedResetQueryPool = true;
        }
    }

    // 测试 vkSetEvent
    {
        static bool s_loggedSetEvent = false;
        if (!s_loggedSetEvent) {
            VkEventCreateInfo eventInfo{};
            eventInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
            
            VkEvent testEvent = VK_NULL_HANDLE;
            VkResult result = vkCreateEvent(m_device, &eventInfo, nullptr, &testEvent);
            
            if (result == VK_SUCCESS && testEvent != VK_NULL_HANDLE) {
                VkResult setResult = vkSetEvent(m_device, testEvent);
                
                if (setResult == VK_SUCCESS) {
                    VkResult statusResult = vkGetEventStatus(m_device, testEvent);
                    
                    if (statusResult == VK_EVENT_SET) {
                        GOLOGW("vkSetEvent completed successfully (event is now signaled)");
                    } else {
                        GOLOGE("vkSetEvent: event status verification failed (expected VK_EVENT_SET, got %d)", statusResult);
                    }
                } else {
                    GOLOGE("vkSetEvent failed with error: %d", setResult);
                }
                
                vkDestroyEvent(m_device, testEvent, nullptr);
            } else {
                GOLOGE("vkSetEvent test skipped: event creation failed with error %d", result);
            }
            s_loggedSetEvent = true;
        }
    }

    // 测试 vkSetPrivateData
    {
        static bool s_loggedSetPrivateData = false;
        if (!s_loggedSetPrivateData) {
            auto pSetPrivateData = reinterpret_cast<PFN_vkSetPrivateData>(
                vkGetDeviceProcAddr(m_device, "vkSetPrivateData"));
            
            if (pSetPrivateData) {
                auto pCreatePrivateDataSlot = reinterpret_cast<PFN_vkCreatePrivateDataSlot>(
                    vkGetDeviceProcAddr(m_device, "vkCreatePrivateDataSlot"));
                auto pGetPrivateData = reinterpret_cast<PFN_vkGetPrivateData>(
                    vkGetDeviceProcAddr(m_device, "vkGetPrivateData"));
                auto pDestroyPrivateDataSlot = reinterpret_cast<PFN_vkDestroyPrivateDataSlot>(
                    vkGetDeviceProcAddr(m_device, "vkDestroyPrivateDataSlot"));
                
                if (pCreatePrivateDataSlot && pGetPrivateData && pDestroyPrivateDataSlot) {
                    VkPrivateDataSlotCreateInfo slotInfo{};
                    slotInfo.sType = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO;
                    slotInfo.flags = 0;
                    
                    VkPrivateDataSlot dataSlot = VK_NULL_HANDLE;
                    VkResult result = pCreatePrivateDataSlot(m_device, &slotInfo, nullptr, &dataSlot);
                    
                    if (result == VK_SUCCESS && dataSlot != VK_NULL_HANDLE) {
                        // 测试数据: 使用特殊模式便于识别
                        uint64_t testData = 0x123456789ABCDEF0ULL;
                        
                        // 执行 vkSetPrivateData
                        VkResult setResult = pSetPrivateData(m_device, VK_OBJECT_TYPE_DEVICE, 
                                                             reinterpret_cast<uint64_t>(m_device), 
                                                             dataSlot, testData);
                        
                        if (setResult == VK_SUCCESS) {
                            // 验证: 立即读取数据
                            uint64_t retrievedData = 0;
                            pGetPrivateData(m_device, VK_OBJECT_TYPE_DEVICE, 
                                          reinterpret_cast<uint64_t>(m_device), 
                                          dataSlot, &retrievedData);
                            
                            // 验证数据是否匹配
                            if (retrievedData == testData) {
                                GOLOGW("vkSetPrivateData completed successfully (set and verified data: 0x%llx)", 
                                       static_cast<unsigned long long>(testData));
                            } else {
                                GOLOGE("vkSetPrivateData: data verification failed (expected 0x%llx, got 0x%llx)",
                                       static_cast<unsigned long long>(testData),
                                       static_cast<unsigned long long>(retrievedData));
                            }
                        } else {
                            GOLOGE("vkSetPrivateData failed with error: %d", setResult);
                        }
                        
                        // 清理资源
                        pDestroyPrivateDataSlot(m_device, dataSlot, nullptr);
                    } else {
                        GOLOGE("vkSetPrivateData test skipped: private data slot creation failed with error %d", result);
                    }
                } else {
                    GOLOGE("vkSetPrivateData test skipped: required helper functions NOT available");
                }
            } else {
                GOLOGE("vkSetPrivateData function NOT available (requires Vulkan 1.3 support)");
            }
            s_loggedSetPrivateData = true;
        }
    }

    // 测试 vkSignalSemaphore
    {
        static bool s_loggedSignalSemaphore = false;
        if (!s_loggedSignalSemaphore) {
            auto pSignalSemaphore = reinterpret_cast<PFN_vkSignalSemaphore>(
                vkGetDeviceProcAddr(m_device, "vkSignalSemaphore"));
            
            if (pSignalSemaphore) {
                // 创建timeline semaphore,初始值为0
                VkSemaphoreTypeCreateInfo timelineInfo{};
                timelineInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
                timelineInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
                timelineInfo.initialValue = 0;
                
                VkSemaphoreCreateInfo semaphoreInfo{};
                semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
                semaphoreInfo.pNext = &timelineInfo;
                
                VkSemaphore timelineSemaphore = VK_NULL_HANDLE;
                VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &timelineSemaphore);
                
                if (result == VK_SUCCESS && timelineSemaphore != VK_NULL_HANDLE) {
                    // 使用vkSignalSemaphore在host端signal到值10
                    VkSemaphoreSignalInfo signalInfo{};
                    signalInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO;
                    signalInfo.semaphore = timelineSemaphore;
                    signalInfo.value = 10;
                    
                    VkResult signalResult = pSignalSemaphore(m_device, &signalInfo);
                    
                    if (signalResult == VK_SUCCESS) {
                        // 验证: 读取semaphore counter值
                        auto pGetSemaphoreCounterValue = reinterpret_cast<PFN_vkGetSemaphoreCounterValue>(
                            vkGetDeviceProcAddr(m_device, "vkGetSemaphoreCounterValue"));
                        
                        if (pGetSemaphoreCounterValue) {
                            uint64_t counterValue = 0;
                            VkResult getResult = pGetSemaphoreCounterValue(m_device, timelineSemaphore, &counterValue);
                            
                            if (getResult == VK_SUCCESS && counterValue == 10) {
                                GOLOGW("vkSignalSemaphore completed successfully (signaled to value: %llu)", 
                                       static_cast<unsigned long long>(counterValue));
                            } else {
                                GOLOGE("vkSignalSemaphore: value verification failed (expected 10, got %llu with result %d)",
                                       static_cast<unsigned long long>(counterValue), getResult);
                            }
                        } else {
                            GOLOGW("vkSignalSemaphore completed successfully (cannot verify value: vkGetSemaphoreCounterValue not available)");
                        }
                    } else {
                        GOLOGE("vkSignalSemaphore failed with error: %d", signalResult);
                    }
                    
                    vkDestroySemaphore(m_device, timelineSemaphore, nullptr);
                } else {
                    GOLOGE("vkSignalSemaphore test skipped: timeline semaphore creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkSignalSemaphore function NOT available (requires Vulkan 1.2+ support)");
            }
            s_loggedSignalSemaphore = true;
        }
    }

    // 测试 vkTrimCommandPool
    {
        static bool s_loggedTrimCommandPool = false;
        if (!s_loggedTrimCommandPool) {
            auto pTrimCommandPool = reinterpret_cast<PFN_vkTrimCommandPool>(
                vkGetDeviceProcAddr(m_device, "vkTrimCommandPool"));
            
            if (pTrimCommandPool) {
                VkCommandPoolCreateInfo poolInfo{};
                poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                poolInfo.queueFamilyIndex = 0;
                poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
                
                VkCommandPool testPool = VK_NULL_HANDLE;
                VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &testPool);
                
                if (result == VK_SUCCESS && testPool != VK_NULL_HANDLE) {
                    VkCommandBufferAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                    allocInfo.commandPool = testPool;
                    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                    allocInfo.commandBufferCount = 1;
                    
                    VkCommandBuffer testCmdBuffer = VK_NULL_HANDLE;
                    result = vkAllocateCommandBuffers(m_device, &allocInfo, &testCmdBuffer);
                    
                    if (result == VK_SUCCESS && testCmdBuffer != VK_NULL_HANDLE) {
                        vkFreeCommandBuffers(m_device, testPool, 1, &testCmdBuffer);
                        
                        pTrimCommandPool(m_device, testPool, 0);
                        GOLOGW("vkTrimCommandPool completed successfully");
                    } else {
                        GOLOGE("vkTrimCommandPool test: command buffer allocation failed with error %d", result);
                    }
                    
                    vkDestroyCommandPool(m_device, testPool, nullptr);
                } else {
                    GOLOGE("vkTrimCommandPool test skipped: command pool creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkTrimCommandPool function NOT available (requires Vulkan 1.1+ support)");
            }
            s_loggedTrimCommandPool = true;
        }
    }

    // 测试 vkUpdateDescriptorSetWithTemplate
    {
        static bool s_loggedUpdateDescriptorSetWithTemplate = false;
        if (!s_loggedUpdateDescriptorSetWithTemplate) {
            auto pCreateDescriptorUpdateTemplate = reinterpret_cast<PFN_vkCreateDescriptorUpdateTemplate>(
                vkGetDeviceProcAddr(m_device, "vkCreateDescriptorUpdateTemplate"));
            auto pUpdateDescriptorSetWithTemplate = reinterpret_cast<PFN_vkUpdateDescriptorSetWithTemplate>(
                vkGetDeviceProcAddr(m_device, "vkUpdateDescriptorSetWithTemplate"));
            auto pDestroyDescriptorUpdateTemplate = reinterpret_cast<PFN_vkDestroyDescriptorUpdateTemplate>(
                vkGetDeviceProcAddr(m_device, "vkDestroyDescriptorUpdateTemplate"));
            
            if (pCreateDescriptorUpdateTemplate && pUpdateDescriptorSetWithTemplate && pDestroyDescriptorUpdateTemplate) {
                VkDescriptorSetLayoutBinding binding{};
                binding.binding = 0;
                binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                binding.descriptorCount = 1;
                binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
                
                VkDescriptorSetLayoutCreateInfo layoutInfo{};
                layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
                layoutInfo.bindingCount = 1;
                layoutInfo.pBindings = &binding;
                
                VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
                VkResult result = vkCreateDescriptorSetLayout(m_device, &layoutInfo, nullptr, &setLayout);
                
                if (result == VK_SUCCESS && setLayout != VK_NULL_HANDLE) {
                    VkDescriptorUpdateTemplateEntry entry{};
                    entry.dstBinding = 0;
                    entry.dstArrayElement = 0;
                    entry.descriptorCount = 1;
                    entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                    entry.offset = 0;
                    entry.stride = sizeof(VkDescriptorBufferInfo);
                    
                    VkDescriptorUpdateTemplateCreateInfo templateInfo{};
                    templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
                    templateInfo.descriptorUpdateEntryCount = 1;
                    templateInfo.pDescriptorUpdateEntries = &entry;
                    templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
                    templateInfo.descriptorSetLayout = setLayout;
                    
                    VkDescriptorUpdateTemplate updateTemplate = VK_NULL_HANDLE;
                    result = pCreateDescriptorUpdateTemplate(m_device, &templateInfo, nullptr, &updateTemplate);
                    
                    if (result == VK_SUCCESS && updateTemplate != VK_NULL_HANDLE) {
                        VkDescriptorPoolSize poolSize{};
                        poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                        poolSize.descriptorCount = 1;
                        
                        VkDescriptorPoolCreateInfo poolInfo{};
                        poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
                        poolInfo.maxSets = 1;
                        poolInfo.poolSizeCount = 1;
                        poolInfo.pPoolSizes = &poolSize;
                        
                        VkDescriptorPool descPool = VK_NULL_HANDLE;
                        result = vkCreateDescriptorPool(m_device, &poolInfo, nullptr, &descPool);
                        
                        if (result == VK_SUCCESS && descPool != VK_NULL_HANDLE) {
                            VkDescriptorSetAllocateInfo allocInfo{};
                            allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
                            allocInfo.descriptorPool = descPool;
                            allocInfo.descriptorSetCount = 1;
                            allocInfo.pSetLayouts = &setLayout;
                            
                            VkDescriptorSet descSet = VK_NULL_HANDLE;
                            result = vkAllocateDescriptorSets(m_device, &allocInfo, &descSet);
                            
                            if (result == VK_SUCCESS && descSet != VK_NULL_HANDLE) {
                                VkBufferCreateInfo bufferInfo{};
                                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                                bufferInfo.size = 256;
                                bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
                                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                                
                                VkBuffer testBuffer = VK_NULL_HANDLE;
                                result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &testBuffer);
                                
                                if (result == VK_SUCCESS && testBuffer != VK_NULL_HANDLE) {
                                    VkMemoryRequirements memReqs;
                                    vkGetBufferMemoryRequirements(m_device, testBuffer, &memReqs);
                                    
                                    VkMemoryAllocateInfo allocMemInfo{};
                                    allocMemInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                                    allocMemInfo.allocationSize = memReqs.size;
                                    allocMemInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                                    
                                    VkDeviceMemory testMemory = VK_NULL_HANDLE;
                                    result = vkAllocateMemory(m_device, &allocMemInfo, nullptr, &testMemory);
                                    
                                    if (result == VK_SUCCESS && testMemory != VK_NULL_HANDLE) {
                                        result = vkBindBufferMemory(m_device, testBuffer, testMemory, 0);
                                        
                                        if (result == VK_SUCCESS) {
                                            VkDescriptorBufferInfo bufferDescInfo{};
                                            bufferDescInfo.buffer = testBuffer;
                                            bufferDescInfo.offset = 0;
                                            bufferDescInfo.range = 256;
                                            
                                            pUpdateDescriptorSetWithTemplate(m_device, descSet, updateTemplate, &bufferDescInfo);
                                            GOLOGW("vkUpdateDescriptorSetWithTemplate completed successfully");
                                        } else {
                                            GOLOGE("vkUpdateDescriptorSetWithTemplate test: buffer binding failed with error %d", result);
                                        }
                                        
                                        vkFreeMemory(m_device, testMemory, nullptr);
                                    } else {
                                        GOLOGE("vkUpdateDescriptorSetWithTemplate test: memory allocation failed with error %d", result);
                                    }
                                    
                                    vkDestroyBuffer(m_device, testBuffer, nullptr);
                                } else {
                                    GOLOGE("vkUpdateDescriptorSetWithTemplate test: buffer creation failed with error %d", result);
                                }
                            } else {
                                GOLOGE("vkUpdateDescriptorSetWithTemplate test: descriptor set allocation failed with error %d", result);
                            }
                            
                            vkDestroyDescriptorPool(m_device, descPool, nullptr);
                        } else {
                            GOLOGE("vkUpdateDescriptorSetWithTemplate test: descriptor pool creation failed with error %d", result);
                        }
                        
                        pDestroyDescriptorUpdateTemplate(m_device, updateTemplate, nullptr);
                    } else {
                        GOLOGE("vkUpdateDescriptorSetWithTemplate test: template creation failed with error %d", result);
                    }
                    
                    vkDestroyDescriptorSetLayout(m_device, setLayout, nullptr);
                } else {
                    GOLOGE("vkUpdateDescriptorSetWithTemplate test skipped: descriptor set layout creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkUpdateDescriptorSetWithTemplate function NOT available (requires Vulkan 1.1+ support)");
            }
            s_loggedUpdateDescriptorSetWithTemplate = true;
        }
    }

    // 测试 vkWaitSemaphores
    {
        static bool s_loggedWaitSemaphores = false;
        if (!s_loggedWaitSemaphores) {
            auto pWaitSemaphores = reinterpret_cast<PFN_vkWaitSemaphores>(
                vkGetDeviceProcAddr(m_device, "vkWaitSemaphores"));
            auto pSignalSemaphore = reinterpret_cast<PFN_vkSignalSemaphore>(
                vkGetDeviceProcAddr(m_device, "vkSignalSemaphore"));
            auto pGetSemaphoreCounterValue = reinterpret_cast<PFN_vkGetSemaphoreCounterValue>(
                vkGetDeviceProcAddr(m_device, "vkGetSemaphoreCounterValue"));
            
            if (pWaitSemaphores && pSignalSemaphore) {
                // 创建timeline semaphore,初始值为0
                VkSemaphoreTypeCreateInfo timelineInfo{};
                timelineInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
                timelineInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
                timelineInfo.initialValue = 0;
                
                VkSemaphoreCreateInfo semaphoreInfo{};
                semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
                semaphoreInfo.pNext = &timelineInfo;
                
                VkSemaphore timelineSemaphore = VK_NULL_HANDLE;
                VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &timelineSemaphore);
                
                if (result == VK_SUCCESS && timelineSemaphore != VK_NULL_HANDLE) {
                    // 先signal到值5
                    VkSemaphoreSignalInfo signalInfo{};
                    signalInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO;
                    signalInfo.semaphore = timelineSemaphore;
                    signalInfo.value = 5;
                    
                    VkResult signalResult = pSignalSemaphore(m_device, &signalInfo);
                    
                    if (signalResult == VK_SUCCESS) {
                        // 验证signal成功(可选,如果有vkGetSemaphoreCounterValue)
                        if (pGetSemaphoreCounterValue) {
                            uint64_t currentValue = 0;
                            pGetSemaphoreCounterValue(m_device, timelineSemaphore, &currentValue);
                            if (currentValue != 5) {
                                GOLOGE("vkWaitSemaphores test: semaphore value verification failed before wait (expected 5, got %llu)",
                                       static_cast<unsigned long long>(currentValue));
                            }
                        }
                        
                        // 等待值5(应该立即返回,因为已经signal到5)
                        uint64_t waitValue = 5;
                        VkSemaphoreWaitInfo waitInfo{};
                        waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
                        waitInfo.flags = 0;
                        waitInfo.semaphoreCount = 1;
                        waitInfo.pSemaphores = &timelineSemaphore;
                        waitInfo.pValues = &waitValue;
                        
                        VkResult waitResult = pWaitSemaphores(m_device, &waitInfo, UINT64_MAX);
                        
                        if (waitResult == VK_SUCCESS) {
                            GOLOGW("vkWaitSemaphores completed successfully (waited for value: %llu)", 
                                   static_cast<unsigned long long>(waitValue));
                        } else if (waitResult == VK_TIMEOUT) {
                            GOLOGE("vkWaitSemaphores returned VK_TIMEOUT (unexpected after signal)");
                        } else {
                            GOLOGE("vkWaitSemaphores failed with error: %d", waitResult);
                        }
                    } else {
                        GOLOGE("vkWaitSemaphores test: semaphore signaling failed with error %d", signalResult);
                    }
                    
                    vkDestroySemaphore(m_device, timelineSemaphore, nullptr);
                } else {
                    GOLOGE("vkWaitSemaphores test skipped: timeline semaphore creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkWaitSemaphores function NOT available (requires Vulkan 1.2+ support)");
            }
            s_loggedWaitSemaphores = true;
        }
    }

    // 测试 vkAcquireNextImage2KHR
    {
        static bool s_loggedAcquireNextImage2KHR = false;
        if (!s_loggedAcquireNextImage2KHR) {
            auto pAcquireNextImage2KHR = reinterpret_cast<PFN_vkAcquireNextImage2KHR>(
                vkGetDeviceProcAddr(m_device, "vkAcquireNextImage2KHR"));
            
            if (pAcquireNextImage2KHR) {
                // 需要有效的swapchain,使用已存在的m_swapChain
                if (m_swapChain != VK_NULL_HANDLE) {
                    // 创建临时semaphore用于测试
                    VkSemaphoreCreateInfo semaphoreInfo{};
                    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
                    
                    VkSemaphore testSemaphore = VK_NULL_HANDLE;
                    VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &testSemaphore);
                    
                    if (result == VK_SUCCESS && testSemaphore != VK_NULL_HANDLE) {
                        VkAcquireNextImageInfoKHR acquireInfo{};
                        acquireInfo.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR;
                        acquireInfo.swapchain = m_swapChain;
                        acquireInfo.timeout = 0; // 非阻塞测试
                        acquireInfo.semaphore = testSemaphore;
                        acquireInfo.fence = VK_NULL_HANDLE;
                        acquireInfo.deviceMask = 1;
                        
                        uint32_t imageIndex = 0;
                        VkResult acquireResult = pAcquireNextImage2KHR(m_device, &acquireInfo, &imageIndex);
                        
                        if (acquireResult == VK_SUCCESS || acquireResult == VK_NOT_READY || acquireResult == VK_SUBOPTIMAL_KHR) {
                            GOLOGW("vkAcquireNextImage2KHR completed successfully (result: %d, imageIndex: %u)", 
                                   acquireResult, imageIndex);
                        } else {
                            GOLOGE("vkAcquireNextImage2KHR returned error: %d", acquireResult);
                        }
                        
                        vkDestroySemaphore(m_device, testSemaphore, nullptr);
                    } else {
                        GOLOGE("vkAcquireNextImage2KHR test skipped: semaphore creation failed with error %d", result);
                    }
                } else {
                    GOLOGI("vkAcquireNextImage2KHR test skipped: swapchain not available");
                }
            } else {
                GOLOGE("vkAcquireNextImage2KHR function NOT available (requires Vulkan 1.1+ and VK_KHR_swapchain)");
            }
            s_loggedAcquireNextImage2KHR = true;
        }
    }

    // 测试 vkBindBufferMemory2
    {
        static bool s_loggedBindBufferMemory2 = false;
        if (!s_loggedBindBufferMemory2) {
            auto pBindBufferMemory2 = reinterpret_cast<PFN_vkBindBufferMemory2>(
                vkGetDeviceProcAddr(m_device, "vkBindBufferMemory2"));
            
            if (pBindBufferMemory2) {
                VkBufferCreateInfo bufferInfo{};
                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                bufferInfo.size = 1024;
                bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                
                VkBuffer testBuffer = VK_NULL_HANDLE;
                VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &testBuffer);
                
                if (result == VK_SUCCESS && testBuffer != VK_NULL_HANDLE) {
                    VkMemoryRequirements memReqs;
                    vkGetBufferMemoryRequirements(m_device, testBuffer, &memReqs);
                    
                    VkMemoryAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                    allocInfo.allocationSize = memReqs.size;
                    allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                    
                    VkDeviceMemory testMemory = VK_NULL_HANDLE;
                    result = vkAllocateMemory(m_device, &allocInfo, nullptr, &testMemory);
                    
                    if (result == VK_SUCCESS && testMemory != VK_NULL_HANDLE) {
                        VkBindBufferMemoryInfo bindInfo{};
                        bindInfo.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO;
                        bindInfo.buffer = testBuffer;
                        bindInfo.memory = testMemory;
                        bindInfo.memoryOffset = 0;
                        
                        VkResult bindResult = pBindBufferMemory2(m_device, 1, &bindInfo);
                        
                        if (bindResult == VK_SUCCESS) {
                            GOLOGW("vkBindBufferMemory2 completed successfully");
                        } else {
                            GOLOGE("vkBindBufferMemory2 failed with error: %d", bindResult);
                        }
                        
                        vkFreeMemory(m_device, testMemory, nullptr);
                    } else {
                        GOLOGE("vkBindBufferMemory2 test skipped: memory allocation failed with error %d", result);
                    }
                    
                    vkDestroyBuffer(m_device, testBuffer, nullptr);
                } else {
                    GOLOGE("vkBindBufferMemory2 test skipped: buffer creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkBindBufferMemory2 function NOT available (requires Vulkan 1.1+ support)");
            }
            s_loggedBindBufferMemory2 = true;
        }
    }

    // 测试 vkBindImageMemory2
    {
        static bool s_loggedBindImageMemory2 = false;
        if (!s_loggedBindImageMemory2) {
            auto pBindImageMemory2 = reinterpret_cast<PFN_vkBindImageMemory2>(
                vkGetDeviceProcAddr(m_device, "vkBindImageMemory2"));
            
            if (pBindImageMemory2) {
                VkImageCreateInfo imageInfo{};
                imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                imageInfo.imageType = VK_IMAGE_TYPE_2D;
                imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
                imageInfo.extent = {256, 256, 1};
                imageInfo.mipLevels = 1;
                imageInfo.arrayLayers = 1;
                imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
                imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
                imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                
                VkImage testImage = VK_NULL_HANDLE;
                VkResult result = vkCreateImage(m_device, &imageInfo, nullptr, &testImage);
                
                if (result == VK_SUCCESS && testImage != VK_NULL_HANDLE) {
                    VkMemoryRequirements memReqs;
                    vkGetImageMemoryRequirements(m_device, testImage, &memReqs);
                    
                    VkMemoryAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                    allocInfo.allocationSize = memReqs.size;
                    allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                    
                    VkDeviceMemory testMemory = VK_NULL_HANDLE;
                    result = vkAllocateMemory(m_device, &allocInfo, nullptr, &testMemory);
                    
                    if (result == VK_SUCCESS && testMemory != VK_NULL_HANDLE) {
                        VkBindImageMemoryInfo bindInfo{};
                        bindInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
                        bindInfo.image = testImage;
                        bindInfo.memory = testMemory;
                        bindInfo.memoryOffset = 0;
                        
                        VkResult bindResult = pBindImageMemory2(m_device, 1, &bindInfo);
                        
                        if (bindResult == VK_SUCCESS) {
                            GOLOGW("vkBindImageMemory2 completed successfully");
                        } else {
                            GOLOGE("vkBindImageMemory2 failed with error: %d", bindResult);
                        }
                        
                        vkFreeMemory(m_device, testMemory, nullptr);
                    } else {
                        GOLOGE("vkBindImageMemory2 test skipped: memory allocation failed with error %d", result);
                    }
                    
                    vkDestroyImage(m_device, testImage, nullptr);
                } else {
                    GOLOGE("vkBindImageMemory2 test skipped: image creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkBindImageMemory2 function NOT available (requires Vulkan 1.1+ support)");
            }
            s_loggedBindImageMemory2 = true;
        }
    }

    // 测试 vkCmdBindVertexBuffers2
    {
        static bool s_loggedCmdBindVertexBuffers2 = false;
        if (!s_loggedCmdBindVertexBuffers2) {
            auto pCmdBindVertexBuffers2 = reinterpret_cast<PFN_vkCmdBindVertexBuffers2>(
                vkGetDeviceProcAddr(m_device, "vkCmdBindVertexBuffers2"));
            
            if (pCmdBindVertexBuffers2) {
                // 创建vertex buffer
                VkBufferCreateInfo bufferInfo{};
                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                bufferInfo.size = 1024;
                bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                
                VkBuffer vertexBuffer = VK_NULL_HANDLE;
                VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &vertexBuffer);
                
                if (result == VK_SUCCESS && vertexBuffer != VK_NULL_HANDLE) {
                    VkMemoryRequirements memReqs;
                    vkGetBufferMemoryRequirements(m_device, vertexBuffer, &memReqs);
                    
                    VkMemoryAllocateInfo allocInfo{};
                    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                    allocInfo.allocationSize = memReqs.size;
                    allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                    
                    VkDeviceMemory vertexMemory = VK_NULL_HANDLE;
                    result = vkAllocateMemory(m_device, &allocInfo, nullptr, &vertexMemory);
                    
                    if (result == VK_SUCCESS && vertexMemory != VK_NULL_HANDLE) {
                        result = vkBindBufferMemory(m_device, vertexBuffer, vertexMemory, 0);
                        
                        if (result == VK_SUCCESS) {
                            // 创建command buffer
                            VkCommandPoolCreateInfo poolInfo{};
                            poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                            poolInfo.queueFamilyIndex = 0;
                            poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                            
                            VkCommandPool tempPool = VK_NULL_HANDLE;
                            result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &tempPool);
                            
                            if (result == VK_SUCCESS && tempPool != VK_NULL_HANDLE) {
                                VkCommandBufferAllocateInfo allocInfo{};
                                allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                                allocInfo.commandPool = tempPool;
                                allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                                allocInfo.commandBufferCount = 1;
                                
                                VkCommandBuffer cmdBuffer = VK_NULL_HANDLE;
                                result = vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
                                
                                if (result == VK_SUCCESS && cmdBuffer != VK_NULL_HANDLE) {
                                    VkCommandBufferBeginInfo beginInfo{};
                                    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                    
                                    result = vkBeginCommandBuffer(cmdBuffer, &beginInfo);
                                    
                                    if (result == VK_SUCCESS) {
                                        VkDeviceSize offset = 0;
                                        VkDeviceSize size = 1024;
                                        VkDeviceSize stride = 32;
                                        
                                        pCmdBindVertexBuffers2(cmdBuffer, 0, 1, &vertexBuffer, &offset, &size, &stride);
                                        
                                        vkEndCommandBuffer(cmdBuffer);
                                        GOLOGW("vkCmdBindVertexBuffers2 completed successfully");
                                    } else {
                                        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                    }
                                } else {
                                    GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                                }
                                
                                vkDestroyCommandPool(m_device, tempPool, nullptr);
                            } else {
                                GOLOGE("vkCreateCommandPool failed with error: %d", result);
                            }
                        } else {
                            GOLOGE("vkBindBufferMemory failed with error: %d", result);
                        }
                        
                        vkFreeMemory(m_device, vertexMemory, nullptr);
                    } else {
                        GOLOGE("vkCmdBindVertexBuffers2 test: memory allocation failed with error %d", result);
                    }
                    
                    vkDestroyBuffer(m_device, vertexBuffer, nullptr);
                } else {
                    GOLOGE("vkCmdBindVertexBuffers2 test skipped: buffer creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkCmdBindVertexBuffers2 function NOT available (requires Vulkan 1.3+ support)");
            }
            s_loggedCmdBindVertexBuffers2 = true;
        }
    }

    // 测试 vkCmdBlitImage2
    {
        static bool s_loggedCmdBlitImage2 = false;
        if (!s_loggedCmdBlitImage2) {
            auto pCmdBlitImage2 = reinterpret_cast<PFN_vkCmdBlitImage2>(
                vkGetDeviceProcAddr(m_device, "vkCmdBlitImage2"));
            
            if (pCmdBlitImage2) {
                // 创建两个compatible的images用于blit测试
                VkImageCreateInfo imageInfo{};
                imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                imageInfo.imageType = VK_IMAGE_TYPE_2D;
                imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
                imageInfo.extent = {256, 256, 1};
                imageInfo.mipLevels = 1;
                imageInfo.arrayLayers = 1;
                imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
                imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
                imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                
                VkImage srcImage = VK_NULL_HANDLE;
                VkImage dstImage = VK_NULL_HANDLE;
                VkResult result = vkCreateImage(m_device, &imageInfo, nullptr, &srcImage);
                
                if (result == VK_SUCCESS && srcImage != VK_NULL_HANDLE) {
                    result = vkCreateImage(m_device, &imageInfo, nullptr, &dstImage);
                    
                    if (result == VK_SUCCESS && dstImage != VK_NULL_HANDLE) {
                        // 分配memory (简化测试,共享memory type查找)
                        VkMemoryRequirements memReqs;
                        vkGetImageMemoryRequirements(m_device, srcImage, &memReqs);
                        
                        VkMemoryAllocateInfo allocInfo{};
                        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                        allocInfo.allocationSize = memReqs.size * 2; // 为两个image分配
                        allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                        
                        VkDeviceMemory imageMemory = VK_NULL_HANDLE;
                        result = vkAllocateMemory(m_device, &allocInfo, nullptr, &imageMemory);
                        
                        if (result == VK_SUCCESS && imageMemory != VK_NULL_HANDLE) {
                            vkBindImageMemory(m_device, srcImage, imageMemory, 0);
                            vkBindImageMemory(m_device, dstImage, imageMemory, memReqs.size);
                            
                            // 创建command buffer
                            VkCommandPoolCreateInfo poolInfo{};
                            poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                            poolInfo.queueFamilyIndex = 0;
                            poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                            
                            VkCommandPool tempPool = VK_NULL_HANDLE;
                            result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &tempPool);
                            
                            if (result == VK_SUCCESS && tempPool != VK_NULL_HANDLE) {
                                VkCommandBufferAllocateInfo allocInfo{};
                                allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                                allocInfo.commandPool = tempPool;
                                allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                                allocInfo.commandBufferCount = 1;
                                
                                VkCommandBuffer cmdBuffer = VK_NULL_HANDLE;
                                result = vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
                                
                                if (result == VK_SUCCESS && cmdBuffer != VK_NULL_HANDLE) {
                                    VkCommandBufferBeginInfo beginInfo{};
                                    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                    
                                    result = vkBeginCommandBuffer(cmdBuffer, &beginInfo);
                                    
                                    if (result == VK_SUCCESS) {
                                        VkImageBlit2 blitRegion{};
                                        blitRegion.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2;
                                        blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                                        blitRegion.srcSubresource.layerCount = 1;
                                        blitRegion.srcOffsets[0] = {0, 0, 0};
                                        blitRegion.srcOffsets[1] = {256, 256, 1};
                                        blitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                                        blitRegion.dstSubresource.layerCount = 1;
                                        blitRegion.dstOffsets[0] = {0, 0, 0};
                                        blitRegion.dstOffsets[1] = {256, 256, 1};
                                        
                                        VkBlitImageInfo2 blitInfo{};
                                        blitInfo.sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2;
                                        blitInfo.srcImage = srcImage;
                                        blitInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
                                        blitInfo.dstImage = dstImage;
                                        blitInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
                                        blitInfo.regionCount = 1;
                                        blitInfo.pRegions = &blitRegion;
                                        blitInfo.filter = VK_FILTER_LINEAR;
                                        
                                        pCmdBlitImage2(cmdBuffer, &blitInfo);
                                        
                                        vkEndCommandBuffer(cmdBuffer);
                                        GOLOGW("vkCmdBlitImage2 completed successfully");
                                    } else {
                                        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                    }
                                } else {
                                    GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                                }
                                
                                vkDestroyCommandPool(m_device, tempPool, nullptr);
                            } else {
                                GOLOGE("vkCreateCommandPool failed with error: %d", result);
                            }
                            
                            vkFreeMemory(m_device, imageMemory, nullptr);
                        } else {
                            GOLOGE("vkCmdBlitImage2 test: memory allocation failed with error %d", result);
                        }
                        
                        vkDestroyImage(m_device, dstImage, nullptr);
                    } else {
                        GOLOGE("vkCmdBlitImage2 test: dst image creation failed with error %d", result);
                    }
                    
                    vkDestroyImage(m_device, srcImage, nullptr);
                } else {
                    GOLOGE("vkCmdBlitImage2 test skipped: src image creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkCmdBlitImage2 function NOT available (requires Vulkan 1.3+ support)");
            }
            s_loggedCmdBlitImage2 = true;
        }
    }

    // 测试 vkCmdCopyBuffer2
    {
        static bool s_loggedCmdCopyBuffer2 = false;
        if (!s_loggedCmdCopyBuffer2) {
            auto pCmdCopyBuffer2 = reinterpret_cast<PFN_vkCmdCopyBuffer2>(
                vkGetDeviceProcAddr(m_device, "vkCmdCopyBuffer2"));
            
            if (pCmdCopyBuffer2) {
                // 创建src和dst buffers
                VkBufferCreateInfo bufferInfo{};
                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                bufferInfo.size = 1024;
                bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                
                VkBuffer srcBuffer = VK_NULL_HANDLE;
                VkBuffer dstBuffer = VK_NULL_HANDLE;
                VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &srcBuffer);
                
                if (result == VK_SUCCESS && srcBuffer != VK_NULL_HANDLE) {
                    result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &dstBuffer);
                    
                    if (result == VK_SUCCESS && dstBuffer != VK_NULL_HANDLE) {
                        VkMemoryRequirements memReqs;
                        vkGetBufferMemoryRequirements(m_device, srcBuffer, &memReqs);
                        
                        VkMemoryAllocateInfo allocInfo{};
                        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                        allocInfo.allocationSize = memReqs.size * 2;
                        allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                        
                        VkDeviceMemory bufferMemory = VK_NULL_HANDLE;
                        result = vkAllocateMemory(m_device, &allocInfo, nullptr, &bufferMemory);
                        
                        if (result == VK_SUCCESS && bufferMemory != VK_NULL_HANDLE) {
                            vkBindBufferMemory(m_device, srcBuffer, bufferMemory, 0);
                            vkBindBufferMemory(m_device, dstBuffer, bufferMemory, memReqs.size);
                            
                            // 创建command buffer
                            VkCommandPoolCreateInfo poolInfo{};
                            poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                            poolInfo.queueFamilyIndex = 0;
                            poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                            
                            VkCommandPool tempPool = VK_NULL_HANDLE;
                            result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &tempPool);
                            
                            if (result == VK_SUCCESS && tempPool != VK_NULL_HANDLE) {
                                VkCommandBufferAllocateInfo allocInfo{};
                                allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                                allocInfo.commandPool = tempPool;
                                allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                                allocInfo.commandBufferCount = 1;
                                
                                VkCommandBuffer cmdBuffer = VK_NULL_HANDLE;
                                result = vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
                                
                                if (result == VK_SUCCESS && cmdBuffer != VK_NULL_HANDLE) {
                                    VkCommandBufferBeginInfo beginInfo{};
                                    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                    
                                    result = vkBeginCommandBuffer(cmdBuffer, &beginInfo);
                                    
                                    if (result == VK_SUCCESS) {
                                        VkBufferCopy2 copyRegion{};
                                        copyRegion.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2;
                                        copyRegion.srcOffset = 0;
                                        copyRegion.dstOffset = 0;
                                        copyRegion.size = 1024;
                                        
                                        VkCopyBufferInfo2 copyInfo{};
                                        copyInfo.sType = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2;
                                        copyInfo.srcBuffer = srcBuffer;
                                        copyInfo.dstBuffer = dstBuffer;
                                        copyInfo.regionCount = 1;
                                        copyInfo.pRegions = &copyRegion;
                                        
                                        pCmdCopyBuffer2(cmdBuffer, &copyInfo);
                                        
                                        vkEndCommandBuffer(cmdBuffer);
                                        GOLOGW("vkCmdCopyBuffer2 completed successfully");
                                    } else {
                                        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                    }
                                } else {
                                    GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                                }
                                
                                vkDestroyCommandPool(m_device, tempPool, nullptr);
                            } else {
                                GOLOGE("vkCreateCommandPool failed with error: %d", result);
                            }
                            
                            vkFreeMemory(m_device, bufferMemory, nullptr);
                        } else {
                            GOLOGE("vkCmdCopyBuffer2 test: memory allocation failed with error %d", result);
                        }
                        
                        vkDestroyBuffer(m_device, dstBuffer, nullptr);
                    } else {
                        GOLOGE("vkCmdCopyBuffer2 test: dst buffer creation failed with error %d", result);
                    }
                    
                    vkDestroyBuffer(m_device, srcBuffer, nullptr);
                } else {
                    GOLOGE("vkCmdCopyBuffer2 test skipped: src buffer creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkCmdCopyBuffer2 function NOT available (requires Vulkan 1.3+ support)");
            }
            s_loggedCmdCopyBuffer2 = true;
        }
    }

    // 测试 vkCmdCopyBufferToImage2
    {
        static bool s_loggedCmdCopyBufferToImage2 = false;
        if (!s_loggedCmdCopyBufferToImage2) {
            auto pCmdCopyBufferToImage2 = reinterpret_cast<PFN_vkCmdCopyBufferToImage2>(
                vkGetDeviceProcAddr(m_device, "vkCmdCopyBufferToImage2"));
            
            if (pCmdCopyBufferToImage2) {
                // 创建buffer
                VkBufferCreateInfo bufferInfo{};
                bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
                bufferInfo.size = 256 * 256 * 4; // RGBA8
                bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
                bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                
                VkBuffer srcBuffer = VK_NULL_HANDLE;
                VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &srcBuffer);
                
                if (result == VK_SUCCESS && srcBuffer != VK_NULL_HANDLE) {
                    // 创建image
                    VkImageCreateInfo imageInfo{};
                    imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                    imageInfo.imageType = VK_IMAGE_TYPE_2D;
                    imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
                    imageInfo.extent = {256, 256, 1};
                    imageInfo.mipLevels = 1;
                    imageInfo.arrayLayers = 1;
                    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
                    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
                    imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                    imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                    
                    VkImage dstImage = VK_NULL_HANDLE;
                    result = vkCreateImage(m_device, &imageInfo, nullptr, &dstImage);
                    
                    if (result == VK_SUCCESS && dstImage != VK_NULL_HANDLE) {
                        VkMemoryRequirements bufferMemReqs;
                        vkGetBufferMemoryRequirements(m_device, srcBuffer, &bufferMemReqs);
                        
                        VkMemoryRequirements imageMemReqs;
                        vkGetImageMemoryRequirements(m_device, dstImage, &imageMemReqs);
                        
                        // 分配buffer memory
                        VkMemoryAllocateInfo bufferAllocInfo{};
                        bufferAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                        bufferAllocInfo.allocationSize = bufferMemReqs.size;
                        bufferAllocInfo.memoryTypeIndex = FindMemoryType(bufferMemReqs.memoryTypeBits, 
                            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
                        
                        VkDeviceMemory bufferMemory = VK_NULL_HANDLE;
                        result = vkAllocateMemory(m_device, &bufferAllocInfo, nullptr, &bufferMemory);
                        
                        if (result == VK_SUCCESS && bufferMemory != VK_NULL_HANDLE) {
                            vkBindBufferMemory(m_device, srcBuffer, bufferMemory, 0);
                            
                            // 分配image memory
                            VkMemoryAllocateInfo imageAllocInfo{};
                            imageAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                            imageAllocInfo.allocationSize = imageMemReqs.size;
                            imageAllocInfo.memoryTypeIndex = FindMemoryType(imageMemReqs.memoryTypeBits, 
                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                            
                            VkDeviceMemory imageMemory = VK_NULL_HANDLE;
                            result = vkAllocateMemory(m_device, &imageAllocInfo, nullptr, &imageMemory);
                            
                            if (result == VK_SUCCESS && imageMemory != VK_NULL_HANDLE) {
                                vkBindImageMemory(m_device, dstImage, imageMemory, 0);
                                
                                // 创建command buffer
                                VkCommandPoolCreateInfo poolInfo{};
                                poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                                poolInfo.queueFamilyIndex = 0;
                                poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                                
                                VkCommandPool tempPool = VK_NULL_HANDLE;
                                result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &tempPool);
                                
                                if (result == VK_SUCCESS && tempPool != VK_NULL_HANDLE) {
                                    VkCommandBufferAllocateInfo allocInfo{};
                                    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                                    allocInfo.commandPool = tempPool;
                                    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                                    allocInfo.commandBufferCount = 1;
                                    
                                    VkCommandBuffer cmdBuffer = VK_NULL_HANDLE;
                                    result = vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
                                    
                                    if (result == VK_SUCCESS && cmdBuffer != VK_NULL_HANDLE) {
                                        VkCommandBufferBeginInfo beginInfo{};
                                        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                        
                                        result = vkBeginCommandBuffer(cmdBuffer, &beginInfo);
                                        
                                        if (result == VK_SUCCESS) {
                                            VkBufferImageCopy2 copyRegion{};
                                            copyRegion.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2;
                                            copyRegion.bufferOffset = 0;
                                            copyRegion.bufferRowLength = 0;
                                            copyRegion.bufferImageHeight = 0;
                                            copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                                            copyRegion.imageSubresource.layerCount = 1;
                                            copyRegion.imageOffset = {0, 0, 0};
                                            copyRegion.imageExtent = {256, 256, 1};
                                            
                                            VkCopyBufferToImageInfo2 copyInfo{};
                                            copyInfo.sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2;
                                            copyInfo.srcBuffer = srcBuffer;
                                            copyInfo.dstImage = dstImage;
                                            copyInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
                                            copyInfo.regionCount = 1;
                                            copyInfo.pRegions = &copyRegion;
                                            
                                            pCmdCopyBufferToImage2(cmdBuffer, &copyInfo);
                                            
                                            vkEndCommandBuffer(cmdBuffer);
                                            GOLOGW("vkCmdCopyBufferToImage2 completed successfully");
                                        } else {
                                            GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                        }
                                    } else {
                                        GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                                    }
                                    
                                    vkDestroyCommandPool(m_device, tempPool, nullptr);
                                } else {
                                    GOLOGE("vkCreateCommandPool failed with error: %d", result);
                                }
                                
                                vkFreeMemory(m_device, imageMemory, nullptr);
                            } else {
                                GOLOGE("vkCmdCopyBufferToImage2 test: image memory allocation failed with error %d", result);
                            }
                            
                            vkFreeMemory(m_device, bufferMemory, nullptr);
                        } else {
                            GOLOGE("vkCmdCopyBufferToImage2 test: buffer memory allocation failed with error %d", result);
                        }
                        
                        vkDestroyImage(m_device, dstImage, nullptr);
                    } else {
                        GOLOGE("vkCmdCopyBufferToImage2 test: image creation failed with error %d", result);
                    }
                    
                    vkDestroyBuffer(m_device, srcBuffer, nullptr);
                } else {
                    GOLOGE("vkCmdCopyBufferToImage2 test skipped: buffer creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkCmdCopyBufferToImage2 function NOT available (requires Vulkan 1.3+ support)");
            }
            s_loggedCmdCopyBufferToImage2 = true;
        }
    }

    // 测试 vkCmdCopyImage2
    {
        static bool s_loggedCmdCopyImage2 = false;
        if (!s_loggedCmdCopyImage2) {
            auto pCmdCopyImage2 = reinterpret_cast<PFN_vkCmdCopyImage2>(
                vkGetDeviceProcAddr(m_device, "vkCmdCopyImage2"));
            
            if (pCmdCopyImage2) {
                // 创建两个compatible的images
                VkImageCreateInfo imageInfo{};
                imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                imageInfo.imageType = VK_IMAGE_TYPE_2D;
                imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
                imageInfo.extent = {256, 256, 1};
                imageInfo.mipLevels = 1;
                imageInfo.arrayLayers = 1;
                imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
                imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
                imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                
                VkImage srcImage = VK_NULL_HANDLE;
                VkImage dstImage = VK_NULL_HANDLE;
                VkResult result = vkCreateImage(m_device, &imageInfo, nullptr, &srcImage);
                
                if (result == VK_SUCCESS && srcImage != VK_NULL_HANDLE) {
                    result = vkCreateImage(m_device, &imageInfo, nullptr, &dstImage);
                    
                    if (result == VK_SUCCESS && dstImage != VK_NULL_HANDLE) {
                        VkMemoryRequirements memReqs;
                        vkGetImageMemoryRequirements(m_device, srcImage, &memReqs);
                        
                        VkMemoryAllocateInfo allocInfo{};
                        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                        allocInfo.allocationSize = memReqs.size * 2;
                        allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, 
                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
                        
                        VkDeviceMemory imageMemory = VK_NULL_HANDLE;
                        result = vkAllocateMemory(m_device, &allocInfo, nullptr, &imageMemory);
                        
                        if (result == VK_SUCCESS && imageMemory != VK_NULL_HANDLE) {
                            vkBindImageMemory(m_device, srcImage, imageMemory, 0);
                            vkBindImageMemory(m_device, dstImage, imageMemory, memReqs.size);
                            
                            // 创建command buffer
                            VkCommandPoolCreateInfo poolInfo{};
                            poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
                            poolInfo.queueFamilyIndex = 0;
                            poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
                            
                            VkCommandPool tempPool = VK_NULL_HANDLE;
                            result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &tempPool);
                            
                            if (result == VK_SUCCESS && tempPool != VK_NULL_HANDLE) {
                                VkCommandBufferAllocateInfo allocInfo{};
                                allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
                                allocInfo.commandPool = tempPool;
                                allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
                                allocInfo.commandBufferCount = 1;
                                
                                VkCommandBuffer cmdBuffer = VK_NULL_HANDLE;
                                result = vkAllocateCommandBuffers(m_device, &allocInfo, &cmdBuffer);
                                
                                if (result == VK_SUCCESS && cmdBuffer != VK_NULL_HANDLE) {
                                    VkCommandBufferBeginInfo beginInfo{};
                                    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
                                    
                                    result = vkBeginCommandBuffer(cmdBuffer, &beginInfo);
                                    
                                    if (result == VK_SUCCESS) {
                                        VkImageCopy2 copyRegion{};
                                        copyRegion.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2;
                                        copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                                        copyRegion.srcSubresource.layerCount = 1;
                                        copyRegion.srcOffset = {0, 0, 0};
                                        copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                                        copyRegion.dstSubresource.layerCount = 1;
                                        copyRegion.dstOffset = {0, 0, 0};
                                        copyRegion.extent = {256, 256, 1};
                                        
                                        VkCopyImageInfo2 copyInfo{};
                                        copyInfo.sType = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2;
                                        copyInfo.srcImage = srcImage;
                                        copyInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
                                        copyInfo.dstImage = dstImage;
                                        copyInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
                                        copyInfo.regionCount = 1;
                                        copyInfo.pRegions = &copyRegion;
                                        
                                        pCmdCopyImage2(cmdBuffer, &copyInfo);
                                        
                                        vkEndCommandBuffer(cmdBuffer);
                                        GOLOGW("vkCmdCopyImage2 completed successfully");
                                    } else {
                                        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
                                    }
                                } else {
                                    GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
                                }
                                
                                vkDestroyCommandPool(m_device, tempPool, nullptr);
                            } else {
                                GOLOGE("vkCreateCommandPool failed with error: %d", result);
                            }
                            
                            vkFreeMemory(m_device, imageMemory, nullptr);
                        } else {
                            GOLOGE("vkCmdCopyImage2 test: memory allocation failed with error %d", result);
                        }
                        
                        vkDestroyImage(m_device, dstImage, nullptr);
                    } else {
                        GOLOGE("vkCmdCopyImage2 test: dst image creation failed with error %d", result);
                    }
                    
                    vkDestroyImage(m_device, srcImage, nullptr);
                } else {
                    GOLOGE("vkCmdCopyImage2 test skipped: src image creation failed with error %d", result);
                }
            } else {
                GOLOGE("vkCmdCopyImage2 function NOT available (requires Vulkan 1.3+ support)");
            }
            s_loggedCmdCopyImage2 = true;
        }
    }

    GOLOGI("=== Vulkan API Smoke Tests Completed ===");
}

void HelloVK::Reset(OHNativeWindow *newWindow, NativeResourceManager *newManager)
{
    m_window.reset(newWindow);
    m_assetManager = newManager;
    OHTestApp::AAssetImporter::Instance().Init(newManager);

    if (m_initialized) {
        CreateSurface();
        RecreateSwapChain();
    }
}

void HelloVK::RecreateSwapChain()
{
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();
    CreateSwapChain();
    CreateImageViews();
    FGCreateDepthResources();
    FGCreateSwapchainSyncObjects();

    FGDestroyColorResources();
    FGCreateColorResources();
    FGDestroyUIRenderer();
    FGDestroyMainSceneRenderer();
    FGInitUIRenderer();
    FGInitMainSceneRenderer();
}

void HelloVK::Render()
{
    // 等待后台初始化完成后才开始渲染
    if (!m_initialized) {
        return;
    }
    FGBalancedInterRender();
}

void HelloVK::OnOrientationChange()
{
    RecreateSwapChain();
    m_orientationChanged = false;
}

void HelloVK::CleanupSwapChain()
{
    m_sceneDepthStencil.Destroy();

    for (auto const &info : m_swapchainInfo) {
        if (info.renderEnd != VK_NULL_HANDLE) {
            GOLOGD("Destroying renderEnd semaphore");
            vkDestroySemaphore(m_device, info.renderEnd, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_swapchainInfo.clear();

    if (m_sceneFramebuffer != VK_NULL_HANDLE) {
        GOLOGD("Destroying framebuffer");
        vkDestroyFramebuffer(m_device, m_sceneFramebuffer, nullptr);
        GOLOGW("vkDestroyFramebuffer completed successfully");
        m_sceneFramebuffer = VK_NULL_HANDLE;
    }

    for (size_t i = 0; i < m_swapChainImageViews.size(); i++) {
        GOLOGD("Destroying image view %zu", i);
        vkDestroyImageView(m_device, m_swapChainImageViews[i], nullptr);
        GOLOGW("vkDestroyImageView completed successfully");
    }

    GOLOGD("Destroying swapchain");
    vkDestroySwapchainKHR(m_device, m_swapChain, nullptr);
    GOLOGW("vkDestroySwapchainKHR completed successfully");
}

void HelloVK::Cleanup()
{
    // 导出性能分析结果
    GOLOGI("=== Exporting Performance Profiling Results ===");
    PerformanceProfiler::Instance().PrintSummary();
    PerformanceProfiler::Instance().ExportToFile();
    PerformanceProfiler::Instance().ExportDetailedRecords();
    GOLOGI("=== Performance data exported ===");
    
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();

    for (auto &info : m_framesInFlights) {
        if (info.commandPool != VK_NULL_HANDLE) {
            GOLOGD("Destroying command pool");
            vkDestroyCommandPool(m_device, info.commandPool, nullptr);
            GOLOGW("vkDestroyCommandPool completed successfully");
        }

        if (info.fence != VK_NULL_HANDLE) {
            GOLOGD("Destroying fence");
            vkDestroyFence(m_device, info.fence, nullptr);
            GOLOGW("vkDestroyFence completed successfully");
        }

        if (info.acquire != VK_NULL_HANDLE) {
            GOLOGD("Destroying acquire semaphore");
            vkDestroySemaphore(m_device, info.acquire, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_framesInFlights.clear();

    GOLOGD("Destroying device");
    vkDestroyDevice(m_device, nullptr);
    GOLOGW("vkDestroyDevice completed successfully");

    if (ENABLE_VALIDATION_LAYERS) {
//        DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
    }

    GOLOGD("Destroying surface");
    vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
    GOLOGW("vkDestroySurfaceKHR completed successfully");
    
    GOLOGD("Destroying instance");
    vkDestroyInstance(m_instance, nullptr);
    GOLOGW("vkDestroyInstance completed successfully");
    m_initialized = false;
}

void HelloVK::SetupDebugMessenger()
{
    if (!ENABLE_VALIDATION_LAYERS) {
        return;
    }

}


std::vector<const char *> HelloVK::GetRequiredExtensions(bool enableValidationLayers)
{
    std::vector<const char *> extensions = { VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME };

    if (enableValidationLayers) {
        extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
    }

    return extensions;
}

void HelloVK::CreateInstance()
{
    // validation layers requested, but not available!
    if (ENABLE_VALIDATION_LAYERS && !CheckValidationLayerSupport()) {
        GOLOGE("Validation layers are unavailable");
        return;
    }
    auto requiredExtensions = GetRequiredExtensions(ENABLE_VALIDATION_LAYERS);

    VkApplicationInfo appInfo{};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Hello Triangle";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "No Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_3;

    VkInstanceCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.pApplicationInfo = &appInfo;
    createInfo.enabledExtensionCount = (uint32_t)requiredExtensions.size();
    createInfo.ppEnabledExtensionNames = requiredExtensions.data();
    createInfo.pApplicationInfo = &appInfo;

    if (ENABLE_VALIDATION_LAYERS) {
//        VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
//        createInfo.enabledLayerCount = static_cast<uint32_t>(m_validationLayers.size());
//        createInfo.ppEnabledLayerNames = m_validationLayers.data();
//        PopulateDebugMessengerCreateInfo(debugCreateInfo);
//        createInfo.pNext = &debugCreateInfo;
    }

    VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateInstance completed successfully");
    } else {
        GOLOGE("vkCreateInstance failed with error: %d", result);
        return;
    }

    if (ENABLE_VALIDATION_LAYERS) {
//        OHTestApp::SetupDebugLabels(m_instance);
    }

    uint32_t extensionCount = 0;
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (count) failed with error: %d", result);
    }
    
    std::vector<VkExtensionProperties> extensions(extensionCount);
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (data) failed with error: %d", result);
    }
}

/*
 * CreateSurface can only be called after the ohos ecosystem has had the
 * chance to provide a native window. This happens after the APP_CMD_START event
 * has had a chance to be called.
 *
 * Notice the window.get() call which is only valid after window has been set to
 * a non null value
 */
void HelloVK::CreateSurface()
{
    if (!m_window) {
        GOLOGE("window not initialized");
        return;
    }

    const VkSurfaceCreateInfoOHOS create_info {
        .sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS,
        .pNext = nullptr,
        .flags = 0,
        .window = m_window.get()
    };

    VkResult result = vkCreateSurfaceOHOS(m_instance, &create_info, nullptr, &m_surface);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSurfaceOHOS completed successfully");
    } else {
        GOLOGE("vkCreateSurfaceOHOS failed with error: %d", result);
    }
}

// BEGIN DEVICE SUITABILITY
// Functions to find a suitable physical device to execute Vulkan commands.

QueueFamilyIndices HelloVK::FindQueueFamilies(VkPhysicalDevice device)
{
    QueueFamilyIndices indices;

    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (count) completed successfully");

    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (data) completed successfully");

    int i = 0;
    for (const auto &queueFamily : queueFamilies) {
        if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            indices.graphicsFamily = i;
        }

        VkBool32 presentSupport = false;
        VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceSupportKHR completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceSupportKHR failed with error: %d", result);
        }
        
        if (presentSupport) {
            indices.presentFamily = i;
        }

        if (indices.isComplete()) {
            break;
        }

        ++i;
    }
    return indices;
}

bool HelloVK::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
    uint32_t extensionCount;
    VkResult result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (count) failed with error: %d", result);
        return false;
    }

    std::vector<VkExtensionProperties> availableExtensions(extensionCount);
    result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (data) failed with error: %d", result);
        return false;
    }

    std::set<std::string> requiredExtensions(m_deviceExtensions.begin(), m_deviceExtensions.end());

    for (const auto &extension : availableExtensions) {
        requiredExtensions.erase(extension.extensionName);
    }

    if (ENABLE_VALIDATION_LAYERS) {
        // Workaround: Probably OHOS Vulkan bug...
//        if (requiredExtensions.size() == 1U && *requiredExtensions.cbegin() == VK_KHR_SWAPCHAIN_EXTENSION_NAME) {
//            return true;
//        }
    }

    return requiredExtensions.empty();
}

SwapChainSupportDetails HelloVK::QuerySwapChainSupport(VkPhysicalDevice device)
{
    SwapChainSupportDetails details;

    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
    }

    uint32_t formatCount;
    result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (count) failed with error: %d", result);
    }

    if (formatCount != 0) {
        details.formats.resize(formatCount);
        result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (data) failed with error: %d", result);
        }
    }

    uint32_t presentModeCount;
    result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (count) failed with error: %d", result);
    }

    if (presentModeCount != 0) {
        details.presentModes.resize(presentModeCount);
        result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, details.presentModes.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (data) failed with error: %d", result);
        }
    }
    return details;
}

bool HelloVK::IsDeviceSuitable(VkPhysicalDevice device)
{
    QueueFamilyIndices indices = FindQueueFamilies(device);
    bool extensionsSupported = CheckDeviceExtensionSupport(device);
    bool swapChainAdequate = false;
    if (extensionsSupported) {
        SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(device);
        swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
    }

    return indices.isComplete() && extensionsSupported && swapChainAdequate;
}

void HelloVK::PickPhysicalDevice()
{
    uint32_t deviceCount = 0;
    VkResult result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (count) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (count) failed with error: %d", result);
        return;
    }

    if (deviceCount <= 0) {
        GOLOGE("failed to find GPUs with Vulkan support!");
        return;
    }

    std::vector<VkPhysicalDevice> devices(deviceCount);
    result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (data) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (data) failed with error: %d", result);
        return;
    }

    for (const auto &device : devices) {
        if (IsDeviceSuitable(device)) {
            m_physicalDevice = device;
            break;
        }
    }

    if (m_physicalDevice == VK_NULL_HANDLE) {
        GOLOGE("failed to find a suitable GPU!");
        return;
    }

    vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_physicalDeviceFeatures);
    GOLOGW("vkGetPhysicalDeviceFeatures completed successfully");
    
    vkGetPhysicalDeviceProperties(m_physicalDevice, &m_physicalDeviceProperties);
    GOLOGW("vkGetPhysicalDeviceProperties completed successfully");
}
// END DEVICE SUITABILITY

void HelloVK::CreateLogicalDeviceAndQueue()
{
    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
    std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
    float queuePriority = 1.0F;
    for (uint32_t queueFamily : uniqueQueueFamilies) {
        VkDeviceQueueCreateInfo queueCreateInfo{};
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.queueFamilyIndex = queueFamily;
        queueCreateInfo.queueCount = 1;
        queueCreateInfo.pQueuePriorities = &queuePriority;
        queueCreateInfos.push_back(queueCreateInfo);
    }

    VkDeviceCreateInfo createInfo{};
    VkPhysicalDeviceFeatures deviceFeatures{};
    VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features{};
    float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
    float16Int8Features.pNext = nullptr;
    float16Int8Features.shaderFloat16 = VK_TRUE;
    float16Int8Features.shaderInt8 = VK_FALSE;
    createInfo.pNext = &float16Int8Features;

    deviceFeatures.samplerAnisotropy = m_physicalDeviceFeatures.samplerAnisotropy;
    deviceFeatures.shaderInt16 = VK_TRUE;
    deviceFeatures.fragmentStoresAndAtomics = VK_TRUE;

    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
    createInfo.pQueueCreateInfos = queueCreateInfos.data();
    createInfo.pEnabledFeatures = &deviceFeatures;
    createInfo.enabledExtensionCount = static_cast<uint32_t>(m_deviceExtensions.size());
    createInfo.ppEnabledExtensionNames = m_deviceExtensions.data();

    VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateDevice completed successfully");
    } else {
        GOLOGE("vkCreateDevice failed with error: %d", result);
        return;
    }

    vkGetDeviceQueue(m_device, indices.graphicsFamily.value(), 0, &m_graphicsQueue);
    GOLOGW("vkGetDeviceQueue (graphics) completed successfully");
    
    vkGetDeviceQueue(m_device, indices.presentFamily.value(), 0, &m_presentQueue);
    GOLOGW("vkGetDeviceQueue (present) completed successfully");
}

void HelloVK::EstablishDisplaySizeIdentity()
{
    VkSurfaceCapabilitiesKHR capabilities;
    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
        return;
    }

    float ratio;
    if (capabilities.currentExtent.width < capabilities.currentExtent.height) {
        ratio = static_cast<float>(capabilities.currentExtent.width) / m_resolution;
    } else {
        ratio = static_cast<float>(capabilities.currentExtent.height) / m_resolution;
    }
    capabilities.currentExtent.width = static_cast<uint32_t>(capabilities.currentExtent.width / ratio);
    capabilities.currentExtent.height = static_cast<uint32_t>(capabilities.currentExtent.height / ratio);

    m_displaySizeIdentity = capabilities.currentExtent;
}

void HelloVK::ExecuteCreateSwapChain(VkSwapchainCreateInfoKHR &createInfo, uint32_t imageCount, VkFormat format)
{
    VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapChain);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSwapchainKHR completed successfully");
    } else {
        GOLOGE("vkCreateSwapchainKHR failed with error: %d", result);
        return;
    }
    
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (count) failed with error: %d", result);
    }
    
    m_swapChainImages.resize(imageCount);
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, m_swapChainImages.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (data) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (data) failed with error: %d", result);
    }

    for (uint32_t i = 0U; i < imageCount; ++i) {
        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "Swapchain image #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "Swapchain image", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for swapchain image #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, m_swapChainImages[i], VK_OBJECT_TYPE_IMAGE, label);
    }

    m_swapChainImageFormat = format;
    m_swapChainExtent = m_displaySizeIdentity;
    GOLOGI("create swapchain image count: %u", imageCount);
}

void HelloVK::CreateSwapChain()
{
    SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(m_physicalDevice);

    auto chooseSwapSurfaceFormat = [](const std::vector<VkSurfaceFormatKHR> &availableFormats) {
        for (const auto &availableFormat : availableFormats) {
            if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
                availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
                return availableFormat;
            }
        }

        return availableFormats[0];
    };

    VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);

    VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

    uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
    if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
        imageCount = swapChainSupport.capabilities.maxImageCount;
    }
    GOLOGI("minSwapchain image count: %u request: %u", swapChainSupport.capabilities.minImageCount, imageCount);
    m_pretransformFlag = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;

    VkSwapchainCreateInfoKHR createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.surface = m_surface;
    createInfo.minImageCount = imageCount;
    createInfo.imageFormat = surfaceFormat.format;
    createInfo.imageColorSpace = surfaceFormat.colorSpace;
    createInfo.imageExtent = m_displaySizeIdentity;
    createInfo.imageArrayLayers = 1;

    createInfo.imageUsage =
        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

    createInfo.preTransform = m_pretransformFlag;

    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()};

    if (indices.graphicsFamily != indices.presentFamily) {
        createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        createInfo.queueFamilyIndexCount = 2U;
        createInfo.pQueueFamilyIndices = queueFamilyIndices;
    } else {
        createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
        createInfo.queueFamilyIndexCount = 0U;
        createInfo.pQueueFamilyIndices = nullptr;
    }

    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
    createInfo.presentMode = presentMode;
    createInfo.clipped = VK_TRUE;
    createInfo.oldSwapchain = VK_NULL_HANDLE;

    ExecuteCreateSwapChain(createInfo, imageCount, surfaceFormat.format);
}

void HelloVK::CreateImageViews()
{
    m_swapChainImageViews.resize(m_swapChainImages.size());
    for (size_t i = 0; i < m_swapChainImages.size(); ++i) {
        VkImageViewCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        createInfo.image = m_swapChainImages[i];
        createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        createInfo.format = m_swapChainImageFormat;
        createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        createInfo.subresourceRange.baseMipLevel = 0;
        createInfo.subresourceRange.levelCount = 1;
        createInfo.subresourceRange.baseArrayLayer = 0;
        createInfo.subresourceRange.layerCount = 1;
        
        VkResult result = vkCreateImageView(m_device, &createInfo, nullptr, &m_swapChainImageViews[i]);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateImageView completed successfully for image %zu", i);
        } else {
            GOLOGE("vkCreateImageView failed with error: %d for image %zu", result, i);
        }
    }
}

void HelloVK::Acquire(VkSemaphore acquire)
{
    PROFILE_PIPELINE_STAGE(AcquireImage);
    PROFILE_API_CALL("vkAcquireNextImageKHR");
    VkResult const result = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire,
        VK_NULL_HANDLE, &m_imageIndex);
    if (result == VK_SUCCESS) {
        if (!s_loggedAcquireNextImage) {
            GOLOGW("vkAcquireNextImageKHR completed successfully");
            s_loggedAcquireNextImage = true;
        }
        return;
    }

    if (result != VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGE("Unexpected acquire result: %d", result);
        return;
    }

    RecreateSwapChain();

    VkResult retryResult = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire, VK_NULL_HANDLE,
        &m_imageIndex);
    if (retryResult == VK_SUCCESS) {
        GOLOGW("vkAcquireNextImageKHR (retry) completed successfully");
    } else {
        GOLOGE("vkAcquireNextImageKHR (retry) failed with error: %d", retryResult);
    }
}

void HelloVK::Present(VkPresentInfoKHR const &presentInfo)
{
    PROFILE_API_CALL("vkQueuePresentKHR");
    VkResult const result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
    if (result == VK_SUCCESS) {
        if (!s_loggedQueuePresent) {
            GOLOGW("vkQueuePresentKHR completed successfully");
            s_loggedQueuePresent = true;
        }
        
        // 周期性导出性能数据(每100帧)
        static uint64_t frameCounter = 0;
        frameCounter++;
        if (frameCounter % 100 == 0) {
            GOLOGI("=== Auto-saving performance data at frame %llu ===", frameCounter);
            
            // 获取Profiler实例并记录
            auto& profiler = PerformanceProfiler::Instance();
            GOLOGI("Profiler instance obtained, calling ExportToFile...");
            profiler.ExportToFile();
            GOLOGI("ExportToFile returned, calling ExportDetailedRecords...");
            profiler.ExportDetailedRecords();
            GOLOGI("ExportDetailedRecords returned");
            
            // 在第2000帧时通过日志导出所有数据
            if (frameCounter == 2000) {
                GOLOGI("=== Exporting all data via logs (for external extraction) ===");
                profiler.ExportViaLogs();
                GOLOGI("=== Log export completed ===");
            }
            
            GOLOGI("=== Auto-save completed at frame %llu ===", frameCounter);
        }
        
        return;
    }

    if (result == VK_SUBOPTIMAL_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_SUBOPTIMAL_KHR");
        m_orientationChanged = true;
        return;
    }

    if (result == VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_ERROR_OUT_OF_DATE_KHR");
        RecreateSwapChain();
        return;
    }

    GOLOGE("Unexpected present result: %d", result);
}

void HelloVK::FGInitDevice()
{
    OHTestApp::Device::Instance().Init(OHTestApp::Device::DeviceDescriptor()
        .Name("Device")
        .Instance(m_instance)
        .PhysicalDevice(m_physicalDevice)
        .LogicalDevice(m_device)
        .QueueFamilyIndex(0)
        .Queue(m_graphicsQueue));
}

void HelloVK::FGCreateColorResources()
{
    m_sceneColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneColor.GetNativeImageView();

    m_predictedColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Predicted Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_predictedColor.GetNativeImageView();
}

void HelloVK::FGDestroyColorResources()
{
    m_sceneColor.Destroy();
    m_predictedColor.Destroy();
}

void HelloVK::FGCreateDepthResources()
{
    VkFormat const format = OHTestApp::Device::Instance().FindDepthFormat();

    m_sceneDepthStencil.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Depth/Stencil")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(format)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneDepthStencil.GetNativeImageView(format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}

void HelloVK::CreateCommandPoolResources(const VkSemaphoreCreateInfo &semaphoreInfo,
    VkCommandPoolCreateInfo const &poolInfo, const VkFenceCreateInfo &fenceInfo,
    VkCommandBufferAllocateInfo &commandBufferAllocateInfo)
{
    for (uint32_t i = 0U; i < OHTestApp::FRAMES_IN_FLIGHT; ++i) {
        FrameInFlight &fif = m_framesInFlights[static_cast<size_t>(i)];
        
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &fif.acquire);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (acquire) completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateSemaphore (acquire) failed with error: %d for frame %u", result, i);
            return;
        }

        result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &fif.commandPool);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateCommandPool completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateCommandPool failed with error: %d for frame %u", result, i);
            return;
        }

        commandBufferAllocateInfo.commandPool = fif.commandPool;
        result = vkAllocateCommandBuffers(m_device, &commandBufferAllocateInfo, &fif.commandBuffer);
        if (result == VK_SUCCESS) {
            GOLOGW("vkAllocateCommandBuffers completed successfully for frame %u", i);
        } else {
            GOLOGE("vkAllocateCommandBuffers failed with error: %d for frame %u", result, i);
            return;
        }

        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "FiF #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "FrameInFlight", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for FiF #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, fif.commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, label);

        result = vkCreateFence(m_device, &fenceInfo, nullptr, &fif.fence);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateFence completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateFence failed with error: %d for frame %u", result, i);
            return;
        }
    }
}

void HelloVK::FGCreateCommandPool()
{
    OHTestApp::CommandPool::Instance().Init(OHTestApp::CommandPool::CommandPoolDescriptor()
        .Name("CommandPool")
        .Device(m_device)
        .Flags(0U)
        .QueueFamilyIndex(OHTestApp::Device::Instance().GetQueueFamilyIndex())
        .Queue(OHTestApp::Device::Instance().GetNativeQueue()));

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    VkCommandPoolCreateInfo const poolInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
        .queueFamilyIndex = OHTestApp::Device::Instance().GetQueueFamilyIndex()
    };

    constexpr VkFenceCreateInfo fenceInfo {
        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_FENCE_CREATE_SIGNALED_BIT
    };

    VkCommandBufferAllocateInfo commandBufferAllocateInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
        .pNext = nullptr,
        .commandPool = VK_NULL_HANDLE,
        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
        .commandBufferCount = 1U
    };

    m_framesInFlights.clear();
    m_framesInFlights.resize(OHTestApp::FRAMES_IN_FLIGHT);
    m_writingCommandBufferIdx = 0U;

    CreateCommandPoolResources(semaphoreInfo, poolInfo, fenceInfo, commandBufferAllocateInfo);
}

void HelloVK::FGCreateSwapchainSyncObjects()
{
    size_t const count = m_swapChainImages.size();
    m_swapchainInfo.clear();
    m_swapchainInfo.resize(count);

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    for (size_t i = 0; i < count; ++i) {
        auto &info = m_swapchainInfo[i];
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &info.renderEnd);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (renderEnd) completed successfully for swapchain image %zu", i);
        } else {
            GOLOGE("vkCreateSemaphore (renderEnd) failed with error: %d for swapchain image %zu", result, i);
            return;
        }
    }
}

void HelloVK::FGInitUIRenderer()
{
    OHTestApp::UIRenderer::UIRendererDescriptor desc{};
    desc.frameInFlightNum = OHTestApp::FRAMES_IN_FLIGHT;
    desc.frameBufferNum = m_swapChainImages.size();
    desc.canvasWidth = m_swapChainExtent.width;
    desc.canvasHeight = m_swapChainExtent.height;
    desc.colorFormat = m_swapChainImageFormat;

    for (auto &item : m_swapChainImageViews) {
        desc.colorImageViews.push_back(item);
    }

    OHTestApp::UIRenderer &renderer = OHTestApp::UIRenderer::Instance();
    renderer.Init(desc);

    m_sceneColorBackground = renderer.MakeBackground(m_sceneColor);
    m_predictedColorBackground = renderer.MakeBackground(m_predictedColor);
}

void HelloVK::FGInitMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();

    sceneRenderer.Init(OHTestApp::MainSceneRenderer::MainSceneRendererDescriptor {
        .frameInFlightNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferWidth = m_swapChainExtent.width,
        .frameBufferHeight = m_swapChainExtent.height,
        .colorFormat = m_sceneColor.GetFormat(),
        .depthStencilFormat = m_sceneDepthStencil.GetFormat()
    });

    VkImageView const attachments[] = {m_sceneColor.GetNativeImageView(), m_sceneDepthStencil.GetNativeImageView()};

    VkFramebufferCreateInfo framebufferInfo {
        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U,
        .renderPass = sceneRenderer.GetRenderPass(),
        .attachmentCount = static_cast<uint32_t>(std::size(attachments)),
        .pAttachments = attachments,
        .width = m_swapChainExtent.width,
        .height = m_swapChainExtent.height,
        .layers = 1U
    };

    VkResult result = vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_sceneFramebuffer);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateFramebuffer completed successfully");
    } else {
        GOLOGE("vkCreateFramebuffer failed with error: %d", result);
    }
}

void HelloVK::FGDestroyUIRenderer()
{
    OHTestApp::UIRenderer::Instance().Destroy();
}

void HelloVK::FGDestroyMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer::Instance().Destroy();
}

void HelloVK::RenderAndUpdateCameraInfo(OHTestApp::MainSceneRenderer &sceneRenderer, FrameInFlight *fif,
    uint8_t fifIndex)
{
    sceneRenderer.Render(fif->commandBuffer, m_sceneFramebuffer, static_cast<size_t>(fifIndex));

    m_viewProj = sceneRenderer.GetSceneViewProjMatrix();
    m_invViewProj = glm::inverse(sceneRenderer.GetSceneViewProjMatrix());
}

void HelloVK::FGBalancedInterRender()
{
    PROFILE_PIPELINE_STAGE(FrameStart);

    if (!m_window) {
        return;
    }

    if (m_orientationChanged) {
        OnOrientationChange();
    }

    auto const fifIndex = static_cast<uint8_t>(m_writingCommandBufferIdx);
    FrameInFlight *fif = &m_framesInFlights[m_writingCommandBufferIdx];
    UpdateWritingCommandBufferIdx();

    VkResult result;
    {
        PROFILE_API_CALL("vkWaitForFences");
        result = vkWaitForFences(m_device, 1U, &fif->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
    }
    if (result == VK_SUCCESS) {
        if (!s_loggedWaitForFences) {
            GOLOGW("vkWaitForFences completed successfully");
            s_loggedWaitForFences = true;
        }
    } else {
        GOLOGE("vkWaitForFences failed with error: %d", result);
    }

    ResetStatus(fif);

    VkCommandBufferBeginInfo beginCB = CreateBeginInfo();
    {
        PROFILE_PIPELINE_STAGE(CommandBufferRecord);
        PROFILE_API_CALL("vkBeginCommandBuffer");
        result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    }
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }

    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();
    sceneRenderer.Update(static_cast<uint32_t>(fifIndex));

    OHTestApp::UIRenderer &uiRenderer = OHTestApp::UIRenderer::Instance();
    uiRenderer.Update(static_cast<uint32_t>(fifIndex));

    // 标准渲染流程：渲染场景 -> 绘制UI -> 显示
    {
        PROFILE_PIPELINE_STAGE(DrawCalls);
        RenderAndUpdateCameraInfo(sceneRenderer, fif, fifIndex);
        uiRenderer.Draw(fif->commandBuffer, m_imageIndex, static_cast<uint32_t>(fifIndex), m_sceneColorBackground);
    }

    {
        PROFILE_PIPELINE_STAGE(CommandBufferEnd);
        PROFILE_API_CALL("vkEndCommandBuffer");
        result = vkEndCommandBuffer(fif->commandBuffer);
    }
    if (result == VK_SUCCESS) {
        if (!s_loggedEndCommandBuffer) {
            GOLOGW("vkEndCommandBuffer completed successfully");
            s_loggedEndCommandBuffer = true;
        }
    } else {
        GOLOGE("vkEndCommandBuffer failed with error: %d", result);
    }

    InterRealFrameDisplay(fif);
}

VkSubmitInfo HelloVK::CreateSubmitInfo(FrameInFlight *fif, const VkPipelineStageFlags &waitStage)
{
    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.waitSemaphoreCount = 1U;
    submitInfo.pWaitSemaphores = &fif->acquire;
    submitInfo.pWaitDstStageMask = &waitStage;
    submitInfo.commandBufferCount = 1U;
    submitInfo.pCommandBuffers = &fif->commandBuffer;
    submitInfo.signalSemaphoreCount = 1U;
    submitInfo.pSignalSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    return submitInfo;
}

VkPresentInfoKHR HelloVK::CreatePresentInfo(VkResult &presentResult)
{
    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.waitSemaphoreCount = 1U;
    presentInfo.pWaitSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    presentInfo.swapchainCount = 1U;
    presentInfo.pSwapchains = &m_swapChain;
    presentInfo.pImageIndices = &m_imageIndex;
    presentInfo.pResults = &presentResult;
    return presentInfo;
}

void HelloVK::InterRealFrameDisplay(FrameInFlight *fif)
{
    // 标准Vulkan显示流程
    constexpr VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    
    VkSubmitInfo const submitInfo = CreateSubmitInfo(fif, waitStage);
    VkResult result;
    {
        PROFILE_PIPELINE_STAGE(QueueSubmit);
        PROFILE_API_CALL("vkQueueSubmit");
        result = vkQueueSubmit(m_graphicsQueue, 1U, &submitInfo, fif->fence);
    }
    if (result == VK_SUCCESS) {
        if (!s_loggedQueueSubmit) {
            GOLOGW("vkQueueSubmit completed successfully");
            s_loggedQueueSubmit = true;
        }
    } else {
        GOLOGE("vkQueueSubmit failed with error: %d", result);
    }

    VkResult presentResult = VK_SUCCESS;
    VkPresentInfoKHR const presentInfo = CreatePresentInfo(presentResult);
    {
        PROFILE_PIPELINE_STAGE(QueuePresent);
        Present(presentInfo);
    }
    
    VulkanPipelineProfiler::NextFrame();
}

void HelloVK::UpdateWritingCommandBufferIdx()
{
    m_writingCommandBufferIdx = (m_writingCommandBufferIdx + 1U) % OHTestApp::FRAMES_IN_FLIGHT;
}

VkCommandBufferBeginInfo HelloVK::CreateBeginInfo()
{
    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    return beginInfo;
}

void HelloVK::ResetStatus(FrameInFlight *fif)
{
    VkResult result = vkResetFences(m_device, 1U, &fif->fence);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetFences) {
            GOLOGW("vkResetFences completed successfully");
            s_loggedResetFences = true;
        }
    } else {
        GOLOGE("vkResetFences failed with error: %d", result);
    }

    result = vkResetCommandPool(m_device, fif->commandPool, 0U);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetCommandPool) {
            GOLOGW("vkResetCommandPool completed successfully");
            s_loggedResetCommandPool = true;
        }
    } else {
        GOLOGE("vkResetCommandPool failed with error: %d", result);
    }

    Acquire(fif->acquire);
}

void HelloVK::ResetStatus(FrameInFlight *fif, VkCommandBufferBeginInfo &beginCB)
{
    ResetStatus(fif);
    VkResult result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }
}

} // namespace vkt